Eşsiz Ucuz


93

Belirli bir dizgenin maliyetini belirleyen bir işlev veya program yazın ;

  • Her karakterin maliyeti, karakterin bu dizgede kaç kez meydana geldiğinin sayısına eşittir ve
  • dizgenin maliyeti, karakterlerinin maliyetlerinin toplamıdır.

Örnek

Bir girdi için abaacab, maliyet aşağıdaki şekilde hesaplanır:

a b a a c a b
1   2 3   4    occurrence of a
  1         2  occurrence of b
        1      occurrence of c
1+1+2+3+1+4+2 = 14

Bu nedenle, dize için maliyeti abaacab14.

kurallar

  • Gönderiminizin puanı, yukarıda tanımlandığı gibi kodunuzun maliyetidir, gönderiminiz kendi kaynak koduyla çalışır ve düşük puan daha iyidir.
  • Gönderiniz, yazdırılabilir ASCII karakterleri ve ayrıca gönderiminizde kullanılan tüm karakterleri içeren dizelerde çalışmalıdır.
  • Karakterler yani harf duyarlıdır ave Afarklı karakterlerdir.

testcases

input -> output
"abaacab" -> 14
"Programming Puzzles & Code Golf" -> 47
"" -> 0
"       " -> 28
"abcdefg" -> 7
"aA" -> 2

Liderler Sıralaması


2
-nPerl gibi program bayrakları puanlara göre nasıl sayılır? Geleneksel olarak 1 bayt olarak sayılır, çünkü standart perl -eve perl -ne1 arasındaki düzenleme mesafesi 1'dir, ancak bu zorluk niçin, yinelenenleri sayma amaçları için sayılacak mı?
Value Ink

2
@ValueInk Evet, bence sayma nen adil seçenek.
Laikoni

1
Keşke bu zorluğa beyin fırtınası çözümü olsaydı.
Peter1807,

10
Gönderiminizin puanı
luizfzs

1
Bir karakterin maliyeti olarak tanımlanır how often this character has already occurred in the string, muhtemelen değişen ediyorum how many times the character has occurred up to this pointdaha anlaşılabilir olması için değil 0 ilk kullanım maliyetleri 1,
undergroundmonorail

Yanıtlar:


83

MATL , skor 4

&=Rz

Çevrimiçi deneyin!

açıklama

'ABBA'Bir örnek olarak girişi düşünün .

&=   % Implicit input. Matrix of all equality comparisons
     % STACK: [1 0 0 1;
               0 1 1 0;
               0 1 1 0;
               1 0 0 1]
R    % Upper triangular part
     % STACK: [1 0 0 1;
               0 1 1 0;
               0 0 1 0;
               0 0 0 1]
z    % Number of nonzeros. Implicitly display
     % STACK: 6

14
Doğrusal bir cebir profesörü müsünüz?
Magic Octopus Urn

4
@carusocomputing Aslında bir mobil iletişim profesörü. Matris kullanma eğilimim, Matlab
Luis Mendo'daki

Temiz! Matlab bu alanda büyük mü? Ben hiç GSM'e ya da onun gibi bir şeye hiç bakmadım.
Magic Octopus Urn

2
Bu topluluğa katıldım, sadece bu mükemmel çözümde sizleri takdir ediyorum!
Wboy

1
@carusocomputing Matlab genel olarak mühendislikte çok yaygın bir araç / dildir. Sayısal hesaplamada iyidir: doğrusal cebir, sinyal işleme ve benzeri. Ve yorumlanmış bir dil olarak kullanımı çok kolaydır
Luis Mendo

17

Python , 49 puan

lambda S:sum(1+S.count(C)for[C]in	S)/2

Çevrimiçi deneyin!

Sonra bir sekme var in.

Puan dağılımı:

  • 27 eşsiz karakter için +27
  • 8 çift karakter için +16: ()Camnou
  • 1 üçlü karakter için +6: S

13
Bir bayt kaydetmek için boşluk yerine bir sekme kullanın.
mbomb007

1
@ mbomb007 Sadece aynı fikir vardı :-)
xnor

1
@ mbomb007 Hah, bu bir dahice hile :-)
ETHproductions

14
@ mbomb007 bu sadece sekmelere karşı golf kodunun içindeki uzay savaşını gösteriyor
Erik Outgolfer

2
Form feed'i (Python sözdiziminde boşluk bırakılmasına da izin verilir) kullanmayı önerecektim, ancak değiştireceğiniz boşluk yok.
user2357112

8

T-SQL, skor 775 579! 580

declaRe @ char(876),@x int,@v int=0Select @=q+CHAR(9)from z X:seleCT @x=len(@),@=REPLACE(@,LEFT(@,1),''),@v+=(@x-LEN(@))*(@x-LEN(@)+1)/2IF LEN(@)>0GOTO X prINT @v-1

EDIT : Birkaç değişken düştü, biraz sıkıştırıldı. @22 yerine 16 sembole kadar, tek başına skorumu 117 puan azalttı!

Güzel yarışma, toplam karakter sayımı dışında bir şey için optimizasyon yapma zorunluluğunu seviyorum.

Giriş varchar alanıyla q önceden varolan tabloda, z , bizim ES kurallarına göre . Bu giriş tablosunu içeren veritabanı büyük / küçük harfe duyarlı bir harmanlama yapılmalıdır .

biçimlendirilmiş:

declaRe @ char(876), @x int, @v int=0
Select @=q+CHAR(9)from z
X:
    seleCT @x=len(@)
          ,@=REPLACE(@,LEFT(@,1),'')
          ,@v+=(@x-LEN(@))*(@x-LEN(@)+1)/2
IF LEN(@)>0 GOTO X
prINT @v-1

SQL anahtar kelimeleri büyük / küçük harfe duyarlı değildir, bu yüzden yinelenen harflerin sayısını en aza indirmek için karma harf kullandım ( aaaa daha iyi / daha düşük puan üretir aaaa ).

Ana döngü, ilk karakterin tüm örneklerini çıkarmadan önce ve sonra uzunluğu karşılaştırır. Bu fark, n * (n + 1) / 2 değerinde çalışan toplama eklenir.

SQL LEN()fonksiyonu rahatsız edici boşlukları görmezden geliyor, bu yüzden bir kontrol karakteri eklemek ve sonunda 1 çıkarmak zorunda kaldım.

EDIT : Kendi puanımın 2 puan yanlış hesaplanması (tırnak işaretleri ile ilgili sorun), birinin kasasını değiştirerek 1 azalması düzeltildi R. Ayrıca tamamen farklı bir strateji üzerinde çalışarak, bunu kendi cevabı olarak gönderiyorum.


3
İlk başta puanınızı düşündüm579! ≈ 8.22 x 10^1349
Engineer Toast

8

C (gcc) , puan:  113  103 100   96  91

@Ugoren, @CalculatorFeline, @gastropner, @ l4m2 ve ipuçları için @ JS1'e teşekkürler.

g(char*s){int y[238]={};while(*s)*y-=--y[*s++];*y/=1;}

Sıfır dizisini başlatır, ardından dizedeki her karakterin örnek sayısını izlemek için dizedeki karakterlerin ASCII değerlerini bu dizinin dizinleri olarak kullanır.

Çevrimiçi deneyin!


3
Öneri: gibi, anahtar kelimeler kullanılmaz değişken adları kullanın z, x, c.
Hesap MakinesiFeline

@CalculatorFeline chariçerir c...
Neil

3
Ayrıca, yalnızca 127 element dizisine ihtiyacınız vardır ( \x7fyazdırılamaz) ve lütfen bir açıklama ekleyin.
Hesap MakinesiFeline

1
Partiye geç saatlerde, ancak bu 96 olmalıdır:z;g(char*s){int y[238]={z=0};while(*s)z+=--y[*s++];z/=~0;}
gastropner 15.08.2016

1
g(char*s){int y[238]={};while(*s)*y+=--y[*s++];*y/=~0;}
l4m2

7

JavaScript (ES6), puan 81 78

@Arnauld sayesinde 3 puan kazandı

s=>s.replace(d=/./g,z=>q+=d[z]=-~d[z],q=0)&&q

Orijinal skor-81 özyinelemeli çözüm:

f=([c,...s],d={})=>c?(d[c]=-~d[c])+f(s,d):0



7

Retina , skor 34

s(O`.
M&!`^|(?<=(.))\1*
.

Çevrimiçi deneyin!

açıklama

s(O`.

Girişteki tüm karakterleri, aynı karakterlerin tek bir çalıştırmada gruplandırılması için sıralayarak başlıyoruz. s(Tüm aşamaları için tekli mod (yani yapar aktive .maç linefeeds).

M&!s`^|(?<=(.))\1*

Amaç, bir n karakter dizisini T n karakterine ( n. Üçgen sayı) çevirmektir, çünkü bu karakterin oluşumunun skoru. Bunu yapmak için örtüşen eşleşmeler buluruz. Özellikle, [1, n] ' deki her i için , maça i-1 karakterlerini dahil edeceğiz . Örtüşen bayrak yüzünden tüm bu eşleşmeleri alıyoruz . Bu bize n * (n-1) / 2 = T n-1 = T n - n karakterlerini sadece eşleşmelerden verir. Ancak maç aşaması, bunlara n satır atışı olan çizgiler ile birleştirilecektir .& nmaçlar. Sadece bir problem var. Son maçtan sonra bir satır akışı olmaz, bu nedenle çıktıdaki toplam karakter sayısı ihtiyacımız olandan daha azdır. Bunu, girişin başlangıcını eşleştirerek düzeltiriz; bu, en az bir eşleşme varsa bize tek bir satır başı beslemesi verir.

.

Son olarak dizgede kaç karakter olduğunu sayıyoruz.


6

Haskell, skor 52 51

f(a:b)=1+sum[1|c<-b,c==a]+f b;f _=0

Arasında bir sekme var fve _.

Çevrimiçi deneyin!

Boş dize değeri dizisi s, değeri 0 olan ailk karakter ve bir bdize geri kalanı 1 artı oluşumları olup aiçinde bb artı yinelemeli çağrı.


5

J , skor 16

1#.,@(*+/\"1)&=

Çevrimiçi deneyin!

açıklama

1#.,@(*+/\"1)&=
              =  Self-classify: bit matrix of equality between input
                 and its unique elements.
     (      )&   Apply verb in parentheses to it:
       +/\         running sums
          "1       of each row
      *            multiplied with original matrix.
                 This causes the i'th 1 on each row to be replaced by i.
   ,@            Flatten the resulting matrix
1#.              and interpret as a base-1 number, computing its sum.

Toplamı 1#.yerine kullanmak +/@birkaç puan kazandı ve bir tane daha kaydetmek için monadik bir bağlamda &kullanılabilir @. Tekrarlananlar 1bana fazladan bir puan kazandırıyor ama ondan kurtulamadım.


"sonra" bir çeyrek gün bekler
CalculatorFeline

2
@CalculatorFeline 10 saat sonra hala daha sonra. : P
Zgarb

Şimdi bir sesquisemiday yapalım.
Hesap MakinesiFeline

Şahsen bu formatı TIO cevapları için kod bölümünde doğru bir bayt sayısını yansıtmak için kullanıyorum, belki kullanmak istersin
Conor O'Brien,

5

R , skor: 67 83 95 128

-61 Giuseppe için en iyi ipuçları

function(x,y=table(utf8ToInt(x)))y%*%{y+1}/2

Çevrimiçi deneyin!

Dize kullanılarak bölünür utf8ToIntve her ascii değeri sayılır table. Sonuç, %*%kendisinde + 1 üzerinde bir matris çarpımı yapılarak hesaplanır ve son olarak yarı yarıya ölçülür.


tableyerine kullanın rle; sortaynı zamanda kurtulabilirsiniz (ve [[1]]sonucuna endekslemek zorunda değilsiniz strsplit)
Giuseppe

@Giuseppe Çok teşekkürler. Masa bile düşünmedim, yakında dahil edecek.
MickyT

2
Ben bunun yerine farklı bir değişken adı kullanarak bir kaç bayt kurtarabilir miyiz n(İçinde beri functioniki kez) ve aynı zamanda değişen (n+1)için{n+1}
Giuseppe

puan: 67 . Bununla ilgili bazı değişiklikler, puanı daha da düşürmeyi mümkün kılabilir.
Giuseppe

@Giuseppe ... Yeniden okumalıydım. hoppala
MickyT


4

Pyth , skor 6

İsaacg sayesinde 1 bayt.

+F/V._

Test odası.

Nasıl çalışır

+F/V._
+F/V._QQ  implicit input
  /V      vectorize count: for each element in the first argument,
                           count the number of occurrences of the
                           second argument:
    ._Q       all prefixes of input
       Q      input
+F        fold (reduce) on +, base case 0.

s+0aynıdır +F.
isaacg

İyi! Yapabileceğim en iyi, usaShHGrScQ1 8Z16 içindir. Bir açıklama ekleyebilir misiniz?
Dijital Travma

1
@DigitalTrauma Bir açıklama ekledim.
Leaky Nun

s/LQpuan 4, bu zorluk sonrası özellikleri kullanıyor mu?
Dave


4

Jöle , 7 puan

ċЀQRFS

Açıklama:

   Q    get unique letters
ċЀ     count the occurences of each letter in the original string
    R   [1..n] for n in list of frequencies
     F  flatten list
      S sum
        (implicit output)

Çevrimiçi deneyin!


2
PPCG'ye Hoşgeldiniz!
Laikoni

4

C, 60 bayt, skor 108 95

g(char*s){int y[256]={},z=0;while(*s)z-=--y[*s++];return z;}

Çevrimiçi deneyin!

Genellikle, öncesi ve sonrası artış operatörleri, kod golfü için harikadır, ancak bu zorluğa gerçekten zarar verdiler!

EDIT: Pozitif olanları eklemek yerine negatif sayıları çıkararak, bir sürü puan kazandım. İle değiştirmek for()de while()noktalı virgül yok.



3

C # (.NET Core) , puan ∞ (demek istediğim, 209)

b=>b.Distinct().Select(z=>{var w=b.Count(p=>p==z);return w*(w+1)/2;}).Sum()

Çevrimiçi deneyin!

Puan aşağıdakileri içerir:

using System.Linq;

Bunun bir süre oldu biliyorum ama değiştirebilir return w*(w+1)/2için return-~w*w/2(196 puan). EDIT: 149 puan için Java 8 cevabımın bir portunu oluşturabilirsiniz : Çevrimiçi deneyin. using System.Linq;b=>{int[]x=new int[256];return\nb.Select(z=>++x[z]).Sum();}
Kevin Cruijssen,

1
@KevinCruijssen: Çözümünüzü 111'e düşürdüm:b=>{var x=new int[256];return\nb.Sum(z=>++x[z]);}
raznagul

@raznagul ( * yarım yıllık cevap geliyor * ) 109 ikinci alanı bir sekmeye değiştirirseniz. ;) Çevrimiçi deneyin.
Kevin Cruijssen 21:18

1
İnteraktif derleyici ile @KevinCruijssen (gelen diğer bir yarım yıllık cevap) 49 ve sanırım 48’in altına düşmeyeceğini düşünüyorum. C # cevaplarının ne kadar fazla olursa o kadar okunaklı görünüyorlar. Çevrimiçi deneyin!
birisi


3

PowerShell, puan 64

$z=@{}
$ARGS|% getE*|%{$u+=($Z.$_+=1)};$U

(Puan, Windows standardı olmayan ancak PS'de çalışan tek satırlık bir yeni satıra dayanır).

PS C:\> D:\unique-is-cheap.ps1 (gc D:\unique-is-cheap.ps1 -raw)
64
  • Hashtable sayacı @{}
  • Harfleri tekrar eder; $argsparametre dizisidir - bu durumda giriş dizgisi tek bir öğe dizisi yapar; |%öğeler üzerinde bir foreach döngüsü yapar getE*ve GetEnumerator()dize yöntemiyle eşleştirmek ve dizeyi karakter akışına dönüştürmek için bu kısayolu kullanır .
  • |%Karakterlerin üzerine gelin ve karma girişlerini arttırın, onu çalışan toplamın üzerine ekleyin. ($x+=1)Pars form hem de değişken değiştirir ve kullanım için yeni bir değer verir.
  • Akan toplamı verin.

(İlk yazdığımda $c=@{};$t=0;[char[]]"$args"|%{$c[$_]++;$t+=$c[$_]};$t, 128 puana sahipti ve çok daha düşük olmayacağını hissettim.


1
61 puan / 38 bayt artış ile
uğraşarak


3

Julia 0.6 , 45 bayt, Puan: 77

MATL çözümünden ilham alan:

f(w)=sum(UpperTriangular([z==j for z=w,j=w]))

Çevrimiçi deneyin!

Sayıları kullanarak daha az güzel bir çözüm:

Julia 0.6 , skor: 82

F(w)=sum(l->[l+1]l/2,count(x->x==i,w)for i=Set(w))

Çevrimiçi deneyin!

Puanlamaya dikkat çektiğiniz ve bahşişler için Guiseppe'ye teşekkür ederiz. Bu yorumlar bana yük yüklememe yardımcı oldu.


1
Gönderiminizin sonucu, kodunuzun maliyeti olduğunu düşünüyorum, ki bu
Giuseppe

1
Julia'yı pek iyi tanımıyorum, ancak bazı değişken isimlerini değiştirerek ve bir parantez kümesini kaldırarak puanı 110'a düşürebileceğinizi düşünüyorum . Tek elemanlı bir vektörün geri dönmesine izin verilirse, puanı daha da azaltmak için (x+1)ile değiştirebilirsiniz [x+1].
Giuseppe

İkinci boşluğu bir sekme veya yeni satıra çevirerek bir skoru kaydedebilirsiniz: puan 104 . Ve @Giuseppe [x+1]yerine kullanmak yerine 98 puanına(x+1) düşürür .
Kevin Cruijssen,

3

Java 10, skor: 149 138 137 134 133 130 103 102 101 100

( Bayt: 72 73 74 75 64 62 61 ) Bayt artar, ancak puan azalır. : D

x->{int j=0,q[]=new int[256];for(var    C:x)j+=++q[C];return
j;}

@Nevay sayesinde -28 puan (ve -11 bayt) . @ OlivierGrégoire
sayesinde -1 puan (ve -2 bayt) . Java 8'i Java 10'a dönüştürerek -1 puan (ve -1 bayt).

Açıklama:

Burada dene.

x->{                     // Method with character-array parameter and integer return-type
  int j=0,               //  Result-integer, starting at 0
      q[]=new int[256];  //  Integer-array with 256 times 0
  for(var   C:x)         //  Loop over the characters of the input array
    j+=++q[C];           //   Raise the value in the array by 1,
                         //   and then add it to the result-integer
  return                 //  Return 
  j;}                    //         the result

1
Ve (133) ~kullanıyorsanız kaldırabilirsiniz . j=0return-j;
Nevay,

1
103:x->{int[]q=new int[256];return\nx.chars().map(v->++q[v]).sum();}
Nevay,

1
Kullanmak, fiilen 103 @Nevay jyerine u( returniçerir u) ve bunun yerine boşluklar bir yeni satır ve sekme. EDIT: Hehe, ben bu yorumu yaparken tam olarak düzenleme yaptınız. :)
Kevin Cruijssen

3

F #, skor 120 118

let j z=Seq.countBy id z|>Seq.sumBy(fun x->List.sum[0..snd x])

-2 Kevin Cruijssen'e teşekkürler !

Çevrimiçi deneyin!

Bir Alır stringgirdi olarak. Seq.countByher ayrı karakteri sayımı ile eşleştirir (id kimlik işlevidir) 'a' = 4, 'b' = 2.

Seq.sumByHer harf için sayımını alır ve gelen tüm sayıları toplar 0o mektup için sayımına. Yani eğer 'a' = 4koleksiyon 0, 1, 2, 3, 4birlikte toplanacaksa 10. Sonra Seq.sumBytüm bu toplamları toplar.


2
Sen değiştirerek 2 puanınızı düşürebilir let qiçin let jçünkü qzaten hem kullanılmaktadır Seq.
Kevin Cruijssen 21:18

2

APL (Dyalog) , puan 15

+/1 1⍉+\∘.=⍨⍞

Çevrimiçi deneyin!

 metin girişi al

∘.=⍨ öz eşitlik tablosu

+\ genelinde kümülatif toplam

1 1⍉ köşegen (lit. her iki boyutu da birinci boyutta daralt)

+/ toplam


2

Retina , skor 68 45 43

s`(.)(?<=((\1)|.)+)
$#3$*
1

Çevrimiçi deneyin! Bağlantı skoru gösterir. Düzenleme: sbayrakların yalnızca bir kez uygulanması gereken aşamaları gruplayarak, üst üste binen eşleşmeleri kullanarak ve 20 bayttan daha fazla üç bayt kullanarak @MartinEnder'e teşekkürler . Üçgensel sayıyı farklı şekilde hesaplayarak başka bir bayttan daha fazla tasarruf sağlayarak bir sıralama yapma ihtiyacını önler.



2

Perl 5 puan 91 83

Bölmedeki -pp nedeniyle 2 ekleyen bayrağı kullanır .

$x=$_;$b+=++$a{$_}for(split//,$x);$_=$b

PPCG'ye Hoşgeldiniz!
Laikoni

1
Cevabınızı temel olarak kullanarak ve ipuçları sayfasından bazı teknikleri uygulayarak puanınızı 31'e düşürmeyi başardım: Çevrimiçi deneyin! . $` is automatically print ed after each call so we can use that to store the score and /./ g` $_, içindeki karakterlerden daha ucuz olanların listesini verir split//.
Dom Hastings,

Bunun eski bir zorluk olduğunu biliyorum, ancak puanı daha da azaltabilirsiniz: Çevrimiçi deneyin!
Xcali

2

Octave , 39 bayt, Skor 69

@(a)sum((b=hist(a,unique(1*a))).^2+b)/2

Çevrimiçi deneyin!

Başka bir Octave cevabı olsa da, bu tamamen benim ve farklı bir yaklaşım, artı daha az puan alıyor :).

Yaklaşım ilk önce histogram işlevi kullanılarak elde edilen her bir benzersiz karakterin sayısını (b) bulmaya kadar aşağı kaynar. Sonra her element için formül kullanılarak yapılan 1'den b'ye kadar olan toplamı hesaplıyoruz (b*(b+1))/2. Daha sonra bireysel toplamlar, final notuna toplanır.

Testlerde, parantez içinde parantezlerin maliyeti oldukça yüksek, çünkü birçok kişiye ihtiyaç var. Açık / kapalı parantez sayısını en aza indirmek için soruları yeniden düzenleyerek yaklaşık 88 başlangıç ​​puanından en aza indirdim - bu nedenle şimdi / 2'yi toplamda tek tek değil son olarak değiştirdik ve ayrıca formülü şu şekilde değiştirdim: (b^2+b)/2Bu daha az parantez gerektirir.


1
Ne yazık ki bu boş dize başarısız görünüyor:error: hist: subscript indices must be either positive integers less than 2^31 or logicals
Laikoni

2

Ortak Lisp, skor 286 232 222

(loop with w =(fill(make-list 128)0)as z across(read)sum(incf(elt w(char-code z))))

Common Lisp’in yerleşik operatörlerinin wordy sözdizimi nedeniyle yüksek puan.

Çevrimiçi deneyin!

Ungolfed kodu:

(loop with w = (fill (make-list 128) 0)  ; create a list to count characters
   as z across (read)                   ; for each character of input
   sum (incf (elt w (char-code z))))     ; increase count in list and sum

2

Mathematica, puan 54

Total[#(#+1)/2&@Counts@Characters@#]&

giriş

[ "Abcdefg"]

hftf sayesinde


Total[#(#+1)/2&@Counts@Characters@#]&puanlar 54.
hftf 19:17
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.