Unik itu Murah


93

Tulis fungsi atau program yang menentukan biaya string yang diberikan, di mana

  • biaya masing-masing karakter sama dengan jumlah berapa kali karakter telah terjadi hingga saat ini dalam string, dan
  • biaya string adalah jumlah dari biaya karakternya.

Contoh

Untuk input abaacab, biaya dihitung sebagai berikut:

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

Jadi biaya untuk string abaacabadalah 14.

Aturan

  • Skor kiriman Anda adalah biaya kode Anda sebagaimana didefinisikan di atas , yaitu kiriman Anda dijalankan dengan kode sumbernya sendiri, dengan skor yang lebih rendah lebih baik.
  • Kiriman Anda harus bekerja pada string yang berisi karakter ASCII yang dapat dicetak, ditambah semua karakter yang digunakan dalam kiriman Anda.
  • Karakter bersifat case-sensitive, yaitu adan Amerupakan karakter yang berbeda.

Testcases

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

Papan peringkat


2
Bagaimana bendera program seperti -nuntuk Perl dihitung menuju skor? Secara tradisional dihitung sebagai 1 byte karena jarak sunting antara standar perl -edan perl -ne1, tetapi untuk tantangan ini, akankah npenghitungan untuk keperluan penghitungan duplikat?
Value Ink

2
@ ValueInk Ya, saya pikir menghitung nadalah opsi yang paling adil.
Laikoni

1
Saya benar-benar berharap ada solusi brainfuck untuk tantangan ini.
Peter1807

10
+1 untuk Skor kiriman Anda adalah biaya kode Anda
luizfzs

1
biaya karakter didefinisikan sebagai how often this character has already occurred in the string, saya mungkin akan berubah how many times the character has occurred up to this pointuntuk membuatnya lebih jelas bahwa biaya penggunaan pertama 1, bukan 0
undergroundmonorail

Jawaban:


83

MATL , skor 4

&=Rz

Cobalah online!

Penjelasan

Pertimbangkan input 'ABBA'sebagai contoh.

&=   % 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
Apakah Anda seorang profesor aljabar linier?
Guci Gurita Ajaib

4
@carusocomputing Sebenarnya adalah profesor komunikasi seluler. Kecenderungan saya untuk menggunakan matriks berasal dari bertahun-tahun pemrograman di Matlab
Luis Mendo

Rapi! Apakah Matlab besar di daerah itu? Saya tidak pernah benar-benar melihat ke GSM atau yang seperti itu.
Guci Gurita Ajaib

2
Saya bergabung dengan komunitas ini hanya untuk memuji Anda atas solusi brilian ini!
Wboy

1
@carusocomputing Matlab adalah alat / bahasa yang sangat umum dalam rekayasa secara umum. Ini bagus dalam perhitungan numerik: aljabar linier, pemrosesan sinyal, dan sejenisnya. Dan menjadi bahasa yang ditafsirkan sangat mudah digunakan
Luis Mendo

17

Python , skor 49

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

Cobalah online!

Setelah itu ada tab in.

Rincian skor:

  • +27 untuk 27 karakter unik
  • +16 untuk 8 karakter ganda: ()Camnou
  • +6 untuk 1 char tiga kali lipat: S

13
Gunakan tab alih-alih ruang untuk menyimpan byte.
mbomb007

1
@ mbomb007 Baru saja punya ide yang sama :-)
xnor

1
@ mbomb007 Hah, itu trik jenius :-)
ETHproduksi

14
@ mbomb007 itu hanya tab vs perang ruang di dalam kode
golf

2
Saya akan menyarankan menggunakan form feed (yang juga diizinkan spasi putih dalam sintaks Python), tetapi Anda tidak memiliki spasi lagi untuk menggantikan.
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 : Menjatuhkan beberapa variabel, sedikit dipadatkan. Turun ke 16 @simbol, bukan 22, yang dengan sendirinya mengurangi skor saya dengan 117 poin kekalahan!

Kontes yang bagus, saya suka persyaratan untuk mengoptimalkan selain jumlah total karakter.

Input melalui bidang varchar q di tabel yang sudah ada sebelumnya z , sesuai aturan IO kami . Database yang berisi tabel input ini harus disetel ke susunan case-sensitive .

Diformat:

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

Kata kunci SQL tidak peka huruf besar-kecil, jadi saya menggunakan huruf besar-kecil untuk meminimalkan jumlah surat duplikat ( aaAA menghasilkan skor yang lebih baik / lebih rendah dari aaaa ).

Loop utama membandingkan panjang sebelum dan sesudah melepas semua instance dari karakter pertama. Perbedaan itu n * (n + 1) / 2 ditambahkan ke total berjalan.

Fungsi SQL secara LEN()mengganggu mengabaikan spasi tambahan, jadi saya harus menambahkan karakter kontrol dan mengurangi 1 di akhir.

EDIT : Memperbaiki salah perhitungan skor saya sendiri dengan 2 poin (masalah dengan kutipan penawaran), dikurangi 1 dengan mengubah satu casing R. Juga mengerjakan strategi yang sama sekali berbeda, saya akan memposting itu sebagai jawabannya sendiri.


3
Pada awalnya saya pikir skor Anda adalah579! ≈ 8.22 x 10^1349
Engineer Toast

8

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

Terima kasih kepada @ugoren, @CalculatorFeline, @gastropner, @ l4m2, dan @ JS1 untuk tips mereka.

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

Menginisialisasi array nol, kemudian menggunakan nilai ASCII dari karakter dalam string sebagai indeks untuk array itu untuk melacak jumlah instance dari setiap karakter dalam string.

Cobalah online!


3
Saran: Gunakan nama variabel yang tidak digunakan dalam kata kunci, seperti z, x, c.
CalculatorFeline

@CalculatorFeline chartermasuk c...
Neil

3
Selain itu, Anda hanya perlu array elemen 127 ( \x7ftidak dapat dicetak) dan silakan tambahkan penjelasan.
CalculatorFeline

1
Terlambat ke pesta, tetapi ini harus 96:z;g(char*s){int y[238]={z=0};while(*s)z+=--y[*s++];z/=~0;}
gastropner

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

7

JavaScript (ES6), skor 81 78

Menyimpan 3 poin berkat @Arnauld

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

Solusi rekursif skor-81 asli saya:

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



7

Retina , skor 34

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

Cobalah online!

Penjelasan

s(O`.

Kita mulai dengan menyortir semua karakter dalam input sehingga karakter yang identik dikelompokkan bersama menjadi satu run. The s(mengaktifkan modus singleline untuk semua tahap (yaitu membuat .linefeeds pertandingan).

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

Tujuannya adalah untuk mengubah serangkaian n karakter menjadi karakter T n ( angka segitiga ke- n ) karena itulah skor kemunculan karakter ini. Untuk melakukannya, kami menemukan kecocokan yang tumpang tindih. Khususnya, untuk setiap i dalam [1, n] , kita akan memasukkan karakter i-1 dalam pertandingan. Kami mendapatkan semua pertandingan itu karena bendera yang tumpang tindih &. Itu memberi kita n * (n-1) / 2 = T n-1 = T n - n karakter hanya dari pertandingan. Namun tahap pertandingan akan bergabung ini dengan linefeeds, yang n linefeeds untuk ncocok. Hanya ada satu masalah. Tidak akan ada umpan baris setelah pertandingan terakhir, jadi jumlah keseluruhan karakter dalam output adalah satu kurang dari yang kita butuhkan. Kami memperbaikinya dengan mencocokkan awal input, yang memberi kami satu umpan baris terkemuka jika setidaknya ada satu kecocokan lainnya.

.

Akhirnya, kami hanya menghitung berapa banyak karakter yang ada di string.


6

Haskell, skor 52 51

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

Ada tab di antara fdan _.

Cobalah online!

Nilai string kosong adalah 0. Nilai string s, di mana akarakter pertama dan bsisa string adalah 1 ditambah kemunculan ain bplus panggilan rekursif dengan b.


5

J , skor 16

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

Cobalah online!

Penjelasan

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.

Menggunakan 1#.alih-alih +/@untuk jumlah menyimpan beberapa poin, dan &dapat digunakan sebagai pengganti @dalam konteks monadik untuk menyimpan satu lagi. Pengulangan itu membuat 1saya kehilangan satu poin ekstra, tetapi saya belum bisa menyingkirkannya.


"nanti" menunggu seperempat hari
CalculatorFeline

2
@CalculatorFeline 10 jam kemudian masih lebih baru. : P
Zgarb

Mari kita buat sesquisemiday sekarang.
CalculatorFeline

Saya pribadi menggunakan format ini untuk jawaban TIO untuk mencerminkan jumlah byte yang akurat di bagian kode, mungkin Anda ingin menggunakannya
Conor O'Brien

5

R , skor: 67 83 95 128

-61 Berkat tips top dari Giuseppe

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

Cobalah online!

String dipisah menggunakan utf8ToIntdan setiap nilai ascii dihitung table. Hasilnya dihitung menggunakan melakukan perkalian matriks %*%lebih dari itu sendiri + 1 dan akhirnya setengah.


gunakan tablesebagai ganti rle; Anda dapat menyingkirkannya sortjuga (dan Anda tidak perlu mengindeks [[1]]ke hasil strsplit)
Giuseppe

@ Giuseppe Terima kasih banyak. Aku bahkan tidak memikirkan meja, akan segera bergabung.
MickyT

2
Saya pikir Anda dapat menyimpan beberapa byte lagi dengan menggunakan nama variabel yang berbeda, bukan n(karena dalam functiondua kali) dan juga berubah (n+1)menjadi{n+1}
Giuseppe

skor: 67 . Beberapa variasi dalam hal ini memungkinkan untuk mengurangi skor lebih lanjut.
Giuseppe

@ Giuseppe ... Seharusnya saya membacanya lagi. whoops
MickyT


4

Pyth , skor 6

1 byte berkat isaacg.

+F/V._

Suite uji.

Bagaimana itu bekerja

+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+0sama dengan +F.
isaacg

Baik! Yang terbaik yang bisa saya lakukan adalah usaShHGrScQ1 8Zuntuk 16. Bisakah Anda menambahkan penjelasan?
Digital Trauma

1
@DigitalTrauma Saya telah menambahkan penjelasan.
Leaky Nun

s/LQadalah skor 4, apakah ini menggunakan fitur yang mengatasi tantangan?
Dave


4

Jelly , skor 7

ċЀQRFS

Penjelasan:

   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)

Cobalah online!


2
Selamat datang di PPCG!
Laikoni

4

C, 60 byte, skor 108 95

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

Cobalah online!

Biasanya operator sebelum dan sesudah kenaikan sangat bagus untuk kode golf, tetapi mereka benar-benar terluka pada tantangan ini!

EDIT: Dengan mengurangi jumlah negatif daripada menambahkan yang positif, saya menyimpan banyak skor. Mengganti for()dengan while()menghilangkan titik koma juga.



3

C # (.NET Core) , skor ∞ (maksud saya, 209)

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

Cobalah online!

Skor tersebut meliputi:

using System.Linq;

Saya tahu ini sudah lama, tetapi Anda dapat mengubah return w*(w+1)/2ke return-~w*w/2(skor 196). EDIT: Anda dapat membuat port jawaban Java 8 saya dengan skor 149 : using System.Linq;b=>{int[]x=new int[256];return\nb.Select(z=>++x[z]).Sum();} Cobalah secara online.
Kevin Cruijssen

1
@KevinCruijssen: Saya mendapat solusi Anda dengan skor 111:b=>{var x=new int[256];return\nb.Sum(z=>++x[z]);}
raznagul

@raznagul ( * setengah tahun respons masuk * ) 109 jika Anda mengubah spasi kedua ke sebuah tab. ;) Cobalah online.
Kevin Cruijssen

1
@KevinCruijssen (respons setengah tahun yang lain masuk) 49 dengan kompiler interaktif, dan saya pikir itu tidak akan pernah sampai di bawah 48. Saya merasa aneh bagaimana semakin banyak jawaban C # yang di mainkan golf, semakin mudah dibaca tampaknya selalu menjadi. Cobalah online!
seseorang


3

PowerShell, skor 64

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

(Skor didasarkan pada baris baris baru, yang bukan standar Windows tetapi bekerja di PS).

PS C:\> D:\unique-is-cheap.ps1 (gc D:\unique-is-cheap.ps1 -raw)
64
  • Counter Hashtable @{}
  • Iterate melalui surat-surat; $argsadalah array parameter - dalam hal ini string input menjadikannya array item tunggal; |%melakukan foreach loop pada item, dan menggunakan jalan getE*pintas untuk mencocokkan GetEnumerator()metode string dan memanggilnya untuk mengubah string menjadi aliran karakter.
  • |%loop di atas karakter dan meningkatkan entri hashtable mereka, tambahkan ke total berjalan. The ($x+=1)form dengan parens baik memodifikasi variabel dan output nilai baru untuk digunakan.
  • Keluarkan total yang berjalan.

(Ketika saya pertama kali menulisnya, itu $c=@{};$t=0;[char[]]"$args"|%{$c[$_]++;$t+=$c[$_]};$tdengan skor 128, dan merasa seperti itu tidak akan jauh lebih rendah. Membagi dua menjadi 64 cukup menyenangkan).


1
61 poin / 38 byte dengan mengotak-atik kenaikan
Veskah


3

Julia 0.6 , 45 bytes, Nilai: 77

Terinspirasi oleh solusi MATL:

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

Cobalah online!

Solusi yang kurang cantik, menggunakan hitungan:

Julia 0.6 , skor: 82

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

Cobalah online!

Terima kasih kepada Guiseppe yang telah menunjukkan skor dan tipnya. Komentar-komentar ini banyak membantu saya.


1
Nilai kiriman Anda adalah biaya kode Anda , yang menurut saya adalah 135.
Giuseppe

1
Saya tidak begitu mengenal Julia, tetapi saya pikir Anda dapat mengurangi skor menjadi 110 dengan mengganti beberapa nama variabel dan menghapus satu set tanda kurung. Jika mengembalikan vektor elemen tunggal diizinkan, maka Anda dapat menggantinya (x+1)dengan [x+1]untuk mengurangi skor.
Giuseppe

Anda dapat menyimpan skor dengan mengubah spasi kedua ke tab atau baris baru: skor 104 . Dan tip @Giuseppe menggunakan [x+1]bukannya (x+1)menurunkannya menjadi skor 98 .
Kevin Cruijssen

3

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

( Bytes: 72 73 74 75 64 62 61 ) Bytes naik, tetapi skor turun. : D

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

Skor -28 (dan -11 byte) berkat @Nevay .
Skor -1 (dan -2 byte) berkat @ OlivierGrégoire .
Skor -1 (dan -1 byte) dengan mengonversi Java 8 ke Java 10.

Penjelasan:

Coba di sini.

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
Anda dapat menghapus ~jika Anda menggunakan j=0dan return-j;(133).
Nevay

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

1
@Nevay 103 sebenarnya, ketika saya menggunakan jbukan u( returnberisi u) dan baris baru dan tab bukan spasi. EDIT: Hehe, Anda sudah mengedit tepat ketika saya membuat komentar ini. :)
Kevin Cruijssen

3

F #, skor 120 118

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

-2 Terima kasih kepada Kevin Cruijssen !

Cobalah online!

Mengambil stringsebagai input. Seq.countBypasangkan setiap karakter berbeda dengan hitungannya ( idadalah fungsi identitas) sehingga Anda berakhir dengan koleksi seperti 'a' = 4, 'b' = 2dll.

The Seq.sumBymengambil hitungan untuk setiap huruf dan merangkum semua angka dari 0hitungan untuk surat itu. Jadi jika 'a' = 4koleksi yang akan 0, 1, 2, 3, 4dirangkum adalah 10. Lalu Seq.sumByjumlahkan semua total itu.


2
Anda dapat menurunkan skor Anda dengan 2 dengan mengubah let qke let j, karena qsudah digunakan di keduanya Seq.
Kevin Cruijssen

2

APL (Dyalog) , skor 15

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

Cobalah online!

 dapatkan input teks

∘.=⍨ meja kesetaraan dengan diri sendiri

+\ jumlah kumulatif di seluruh

1 1⍉ diagonal (sedikit jatuhkan kedua dimensi ke dimensi satu)

+/ jumlah


2

Retina , skor 68 45 43

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

Cobalah online! Tautan menunjukkan skor. Sunting: Terima kasih kepada @MartinEnder yang menyimpan 20 byte dengan menggunakan pertandingan yang tumpang tindih alih-alih mencari yang lain dan tiga byte selanjutnya dengan mengelompokkan tahapan sehingga sbendera hanya perlu diterapkan sekali. Menyimpan dua byte lebih lanjut dengan menghitung angka segitiga secara berbeda, menghindari perlunya pengurutan.



2

Perl 5 skor 91 83

Menggunakan -pbendera yang menambahkan 2 karena p di split.

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

Selamat datang di PPCG!
Laikoni

1
Menggunakan jawaban Anda sebagai basis dan menerapkan beberapa teknik dari halaman tips, saya berhasil mendapatkan skor Anda hingga 31: Coba online! . $` is automatically print ed after each call so we can use that to store the score and /./g` mengembalikan daftar semua karakter $_yang lebih murah daripada split//.
Dom Hastings

Saya tahu ini adalah tantangan lama, tetapi Anda dapat memotong skor lebih jauh: Cobalah secara online!
Xcali

2

Oktaf , 39 byte, Skor 69

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

Cobalah online!

Walaupun ada satu lagi jawaban Octave, yang ini sepenuhnya milik saya dan pendekatan yang berbeda, ditambah skornya lebih sedikit :).

Pendekatan ini bermula untuk menemukan jumlah (b) pertama dari setiap karakter unik, yang dicapai dengan menggunakan fungsi histogram. Kemudian untuk setiap elemen kita menghitung jumlah 1 hingga b yang dilakukan menggunakan rumus (b*(b+1))/2. Kemudian jumlah individu semua dijumlahkan ke dalam skor akhir.

Dalam pengujian tampaknya kurung benar-benar mahal dalam penilaian karena banyak yang dibutuhkan. Saya telah dioptimalkan turun dari skor awal sekitar 88 dengan mengatur ulang pertanyaan untuk meminimalkan jumlah kurung buka / tutup - maka kita sekarang melakukan / 2 pada total akhir daripada secara individual, dan juga saya telah memodifikasi rumus untuk (b^2+b)/2karena itu membutuhkan kurung lebih sedikit.


1
Sayangnya ini tampaknya gagal pada string kosong:error: hist: subscript indices must be either positive integers less than 2^31 or logicals
Laikoni

2

Common Lisp, skor 286 232 222

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

Skor bernilai tinggi karena sintaksis bertele-tele dari operator Common Lisp.

Cobalah online!

Kode yang tidak dipisahkan:

(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, skor 54

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

memasukkan

["abcdefg"]

terima kasih kepada hftf


Total[#(#+1)/2&@Counts@Characters@#]&skor 54.
hftf
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.