Nomor Asli (II)


18

Tantangan ini pada dasarnya identik dengan yang satu ini hanya dengan satu perbedaan: sekarang diperbolehkan untuk mengacak huruf di mana saja dalam string.

Skenario

John memiliki nomor penting, dan dia tidak ingin orang lain melihatnya.

Dia memutuskan untuk mengenkripsi nomor tersebut, menggunakan langkah-langkah berikut:

Nomornya selalu merupakan urutan yang tidak menurun (mis. "1123")

Dia mengubah setiap digit menjadi kata-kata bahasa Inggris. (mis. "123" -> "ONETWOTHREE")

Dan kemudian, atur ulang surat secara acak. (mis. "ONETWOTHREE" -> "EEWOOHRNTET")

John merasa bahwa nomornya aman untuk melakukannya. Bahkan, enkripsi seperti itu dapat dengan mudah didekripsi :(


Tugas

Dengan diberikan string terenkripsi, tugas Anda adalah mendekripsi dan mengembalikan nomor aslinya.


Aturan

  • Ini adalah kode golf, jadi jawaban tersingkat dalam byte menang
  • Anda dapat mengasumsikan bahwa string input selalu valid
  • String input hanya berisi huruf besar
  • Nomor aslinya selalu diatur dalam urutan menaik
  • Anda dapat mengembalikan nomor dalam format string atau integer
  • Huruf-huruf hanya akan dikocok di antara satu kata, bukan di antara seluruh string. Huruf-huruf dapat dikocok di mana saja dalam string.
  • Jumlahnya hanya dari 1 hingga 9 inklusif ( ONEhingga NINE)

Kemungkinan String yang Tidak Diuraikan

Berikut adalah daftar string tepat setelah mereka dikonversi ke string dari angka-angka:

 1 -> ONE 
 2 -> TWO
 3 -> THREE
 4 -> FOUR
 5 -> FIVE
 6 -> SIX
 7 -> SEVEN
 8 -> EIGHT
 9 -> NINE

Contohnya

"NEO" -> 1

"NWEOOT" -> 12

"TOEERWNEHOT" -> 123

"IHNEVGENNEISTE" -> 789

"WEETVTRFSVUHNEEFRHIXEOINSNIEGTOONIEE" -> 123456789

"EWHEWROETOTTON" -> 1223

"ONEWESTV" -> 27 (terima kasih, ETHproductions!)


7
Case test yang disarankan: kira-kira seperti "ONEWESTV" -> 27(termasuk angka yang tidak benar-benar muncul)
ETHproduksi

@ ETHproductions Ide bagus! Ditambahkan.
Cristian Lupascu

Kenapa tidak ada "NOL"?
RosLuP

@RLoLuP John membenci nol terkemuka ...
Cristian Lupascu

Jawaban:


9

Python 2 , 123 byte

c=map(input().count,"OWHUFXSGIQ")
i=4
for j in"71735539994":c[i*2]-=c[int(j)];i=-~i%5
s=""
for n in c:i+=1;s+=`i`*n
print s

Program lengkap yang mengambil input dan mencetak nomor John.

Cobalah online! atau lihat test-suite

Bagaimana?

Mari kita bekerja dengan contoh "NEONSEXTOWNII" (untuk menghasilkan 1269, dan jadilah Leisure Suite Larry -esque!)

Pertama c=map(input().count,"OWHUFXSGIQ")mengambil input dan menghitung jumlah masing-masing OWHUFXSGIQ- ini adalah huruf yang muncul di setiap nomor dalam urutan menaik, dengan 2,4,6, dan 8 memiliki huruf "sendiri" mereka ( WUXG), ditambah huruf tambahan, Quntuk menambahkan nol ke akhir dan membuat panjang daftar yang dihasilkan genap. Sebagai contoh:

[2,1,0,0,0,1,1,0,2,0] <- c
 O W H U F X S G I Q  <- is the counts of these letters
 1 2 3 4 5 6 7 8 9 0  <- which "relate to" these digits in John's number
   2   4   6   8   0  <- these will be correct as the letters are unique to their words

Entri untuk 1, 3, 5, 7, dan 9 perlu disesuaikan untuk memperbaiki kelimpahan surat-surat lainnya. Ini dilakukan oleh loop berikutnya:

i=4
for j in"71735539994":c[i*2]-=c[int(j)];i=-~i%5

Perhatikan bahwa entri yang akan disesuaikan adalah entri alternatif (1,3,5,7,9,1,3,5, ...), jadi kita dapat menambahkan dua ke variabel indeks pada setiap langkah dan modulo dengan 10 agar tetap di rentang jika kita perlu melintasi lebih dari sekali (yang kita lakukan). Untuk menghemat beberapa byte, kita bisa menambah satu dan modulo dengan 5 dan menggunakan indeks ganda.
Karena penyesuaian untuk 9 membutuhkan kerja paling banyak kita mulai dari sana - itu berada di indeks 8 jadi kita mulai dari i=4. String "71735539994"kemudian memberikan indeks, jdari nilai-nilai untuk dihapus pada setiap tahap (di mana kami telah memastikan indeks kesembilan akan berisi nol dengan menggunakan "Q"saat membuat c); c[i*2]-=c[int(j)]melakukan penyesuaian masing-masing individu dan i=-~i%5bergerak ike indeks berikutnya (di mana -~iada -(-1-i)atau i+1menyimpan tanda kurung (i+1)%5) menjagai*2dalam batas c.
Jadi, pertama-tama kita kurangi angka pada indeks j=7dari pada indeks i*2=8, dengan mengurangi jumlah "G" yang dihitung dari jumlah "I", menyesuaikan angka "SEMBILAN" dengan jumlah (benar) "EIGHT" s ( yang juga memiliki "Aku"). Kami kemudian pindah ke i=0( -~4%5 = (4+1)%5 = 0), merujuk indeks i*2 = 0yang untuk "ONE" dan mengurangi nilai yang ditemukan pada indeks j=1entri yang menghitung "W" dan karenanya "DUA", menyesuaikan jumlah "O" turun. Pada akhir loop kami memiliki jumlah yang diperbaiki:

[1,1,0,0,0,1,0,0,1,0] <- c   (for 1223333448 it would be: [1,2,4,2,0,0,0,1,0,0])
 1 2 3 4 5 6 7 8 9 0

jadi yang tersisa hanyalah mencetak apa yang csekarang mewakili ( 1269). isekarang kembali 0, jadi kami menambahkannya di awal loop dan menggunakannya sebagai digit kami:

s=""
for n in c:i+=1;s+=`i`*n
print s

Kutu belakang `i`,, adalah singkatan Python2 repr(i)yang mendapatkan representasi string dari objek (karakter digit yang dipertanyakan sebagai string) dan mengalikan string dengan angka menciptakan string baru dari banyak pengulangan (di sini kami hanya menunjukkan n=0berbalik `i`dari mengatakan "5"to ""dan n=1turn keep mengatakan "6"as "6", tetapi juga berfungsi untuk bilangan bulat positif yang lebih besar, jadi "3"*4menjadi "3333"misalnya.)


8

05AB1E , 31 byte

[{‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘#NSèJ{Q#

Cobalah online!

Penjelasan

[                                   # start loop
 {                                  # sort input
  ‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘#            # push the list ['Z','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']
                        N           # push the current iteration counter
                         S          # split to list of digits
                          è         # index into the list with each
                           J{       # join to string and sort
                             Q#     # if the strings are equal, exit loop
                                    # implicitly print iteration counter

Sangat tidak efisien untuk input besar.


‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘# # push the list ['Z','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']: bisa Anda jelaskan sedikit, saya berjuang untuk memahami bagaimana string apa pun dapat dihasilkan.
Cyril Gandon

1
@CyrilGandon: membatasi string kata-kata yang dipisahkan spasi huruf besar terkompresi. Zberarti Z. Semua pasangan 2 simbol lainnya menunjukkan kata yang dikompresi dari kamus 05AB1E . Jadi misalnya €µditerjemahkan sebagai ONE.
Emigna

Bagus, bagaimana Anda mengompres string yang berisi di kamus? Sesuatu dengan nilai unicode pasangan?
Cyril Gandon

1
@CyrilGandon: Anda mengambil nomor baris kata dalam dict (2420 untuk halo ) dan kurangi 1. Ini memberi kita 2419. Simbol yang kita butuhkan adalah simbol yang diikuti oleh 24dan 19dalam dokumen . Dalam kasus kami ini 24=Ÿdan 19=™, demikian HELLOjuga ‘Ÿ™‘
halnya

1
Ada juga kompresor yang ditulis oleh Adnan yang dapat Anda gunakan dalam kebanyakan kasus. Tautannya agak panjang, tetapi Anda bisa menemukannya di ruang obrolan 05AB1E . Itu juga tempat yang baik untuk bertanya apakah ada pertanyaan lebih lanjut :)
Emigna

8

Retina , 112 97 byte

O`.
}`GH
8
X
6
H
3
+`F(.*)O(.*)U
4$1$2
+`O(.*)W
2$1
+`F(.*)V
5$1
+`N(.*)V
7$1
}`NO
1
NN
9
T`L
O`.

Cobalah online!

-12 byte terima kasih kepada @Neil

-3 byte dengan menggunakan kelas karakter L dalam transposisi

Bagaimana itu bekerja

Pada dasarnya, ini bergantung pada kenyataan bahwa huruf hanya digunakan dalam nama-nama angka tertentu. Misalnya SIXadalah satu-satunya nama yang berisi X. Ini semakin rumit dengan kenyataan bahwa beberapa kata tumpang tindih dalam huruf, seperti keduanya FIVEdan SEVENmenggunakan V. Ini dapat diperbaiki dengan mengidentifikasi FIVEdengan F(.*)V.


1
@RickHitchcock Diperbaiki. Rekursi pada konversi ke 8 tidak berfungsi dengan baik
fireflame241

1
@RickHitchcock. Memperbaiki rekursi untuk semuanya.
fireflame241

Mengganggu GHdan NOakan berdekatan, kecuali untuk yang sebelumnya 8atau 1dari substitusi sebelumnya ...
Neil

Mungkin }`GH 8akan berhasil 8- itu }akan menyebabkan karakter diurutkan lagi, sehingga menempatkan yang tersisa Gdan Hbersama - sama.
Neil

@Neil Ide bagus. Saya juga bisa melakukan itu NO -> 1, yang nyaman.
fireflame241

5

Kotlin 1.1 , 359 352 331 327 325 byte

pengajuan

fun r(r:String):String{var s=""
val f=r.split(s).groupingBy{it}.eachCount()
val c=Array(10,{0})
c[8]=f["G"]?:0
c[6]=f["X"]?:0
c[4]=f["U"]?:0
c[2]=f["W"]?:0
c[1]=(f["O"]?:0)-c[2]-c[4]
c[3]=(f["R"]?:0)-c[4]
c[7]=(f["S"]?:0)-c[6]
c[5]=(f["V"]?:0)-c[7]
c[9]=((f["N"]?:0)-c[1]-c[7])/2
for(i in 1..9)for(x in 1..c[i])s+=i
return s}

Tidak berfungsi di TryItOnline karena Kotlin 1.1 tidak didukung

Uji

fun r(r:String):String{
val f=r.split("").groupingBy{it}.eachCount()
val c=Array(10,{0})
c[8]=f["G"]?:0
c[6]=f["X"]?:0
c[4]=f["U"]?:0
c[2]=f["W"]?:0
c[1]=(f["O"]?:0)-c[2]-c[4]
c[3]=(f["R"]?:0)-c[4]
c[7]=(f["S"]?:0)-c[6]
c[5]=(f["V"]?:0)-c[7]
c[9]=((f["N"]?:0)-c[1]-c[7])/2
var s=""
for(i in 1..9)for(x in 1..c[i])s+=i
return s}

data class TestData(val input: String, val output: String)

fun main(vararg args:String) {
    val items = listOf(
    TestData("NEO" , "1"),
    TestData("NWEOOT" , "12"),
    TestData("TOEERWNEHOT" , "123"),
    TestData("IHNEVGENNEISTE" , "789"),
    TestData("WEETVTRFSVUHNEEFRHIXEOINSNIEGTOONIEE" , "123456789"),
    TestData("EWHEWROETOTTON" , "1223")
    )
    for (item in items) {
        val out = r(item.input)
        if (out != item.output) {
            throw AssertionError("Bad result: $item : $out")
        }
    }
}

Logika

Lembar buaian

Saya menggunakan lembar di atas untuk mencari cara paling sederhana untuk menyelesaikan setiap huruf

  • Hijau = Selesaikan sendiri
  • Biru = Membutuhkan hijau untuk dipecahkan
  • Oranye = Perlu blues untuk dipecahkan
  • Merah = Membutuhkan jeruk untuk dipecahkan

Suntingan

  • -7 - Whitespace berubah oleh w0lf
  • -21 - Daftar menyusut Dari ke Array
  • -4 - Menghapus tanda kurung yang tidak dibutuhkan
  • 0 - Menambahkan logika di
  • -2 - Menggunakan kembali string kosong berkat kevin-cruijssen

1
Hanya memperhatikan saya benar-benar terikat dengan Anda dengan jawaban Java 8 saya (127 byte), menggunakan pendekatan yang sama. ;) Tetapi satu pertanyaan: tidak bisakah Anda mengubah var s=""dan return ske r=""dan return rdengan menggunakan kembali String-input, yang tidak lagi Anda perlukan pada saat itu? Saya tidak pernah diprogram di Kotlin sebelumnya, jadi bisa jadi saya berbicara omong kosong di sini. ; p
Kevin Cruijssen


1
Ah ya, itu tentu saja kemungkinan; parameter secara finaldefault. Hmm, satu hal lagi yang bisa Anda mainkan golf: Tempatkan var s=""sebagai hal pertama dalam metode, dan gantikan val f=r.split("").dengan val f=r.split(s).. Sekali lagi, tidak tahu apakah itu berhasil. Sayang sekali TIO belum mendukung v1.1, kalau tidak saya akan mencoba saran ini sendiri sebelum saya membuat diri saya terdengar bodoh ..
Kevin Cruijssen

4

Jelly , 37 byte

1ðDị“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»ŒuḲ¤ẎŒ!ċð1#

Cobalah online!

-1 terima kasih kepada Jonathan Allan .


Ini kali keluar untuk beberapa masukan lebih besar dari 7 karakter (ex: NINEFIVE, THREEFIVE). Apakah ini bug, atau kodenya tidak efisien?
Cristian Lupascu

@ w0lf yang terakhir ( Œ!berarti "permutasi")
Erik the Outgolfer

Simpan satu byte menggunakan "AA" daripada "!":...“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»...
Jonathan Allan

@ Jonathan Allan oh apakah AA sepatah kata?
Erik the Outgolfer

Itu kata pertama dalam kamus pendek, ya.
Jonathan Allan

3

Java 8, 248 234 byte

s->{int x=0,a[]=new int[10];for(String t:"2WO;4UORF;6XSI;8GI;5FI;7S;3R;1O;9I".split(";"))for(;s.indexOf(t.charAt(1))>=0;a[t.charAt(0)-48]++)for(String z:t.split(""))s=s.replaceFirst(z,"");for(s="";x++<9;)for(;a[x]-->0;)s+=x;return s;}

Penjelasan Kode:

s->{
    // Array to count how often which number appears
    int a[]=new int[10];
    // The first character behind the number serves the identification
    // the other characters get removed to identify the other numbers later
    for(String t:"2WO;4UORF;6XSI;8GI;5FI;7S;3R;1O;9I".split(";"))
        // Check if the string contains the id 
        for(;s.indexOf(t.charAt(1))>=0;a[t.charAt(0)-48]++)
            // Remove the relevant charcters
            for(String z:t.split(""))
                s=s.replaceFirst(z,"");
    // Clear the string to write the output
    s="";
    // write the numbers sequential into the output 
    for(int x=0;x++<9;)
        for(;a[x]-->0;)
            s+=x;
    return s;
}

-14 Terima kasih kepada Olivier Grégoire



2

Java 8, 346 345 344 336 327 byte

s->{int g=c(s+=" ","G"),u=c(s,"U"),w=c(s,"W"),x=c(s,"X"),f=c(s,"F")-u,h=c(s,"H")-g,v=c(s,"V")-f,o=c(s,"O")-u-w,i=c(s,"I")-f-x-g;return d(s=d(s=d(s=d(s=d(s=d(s=d(s=d(s=d("",o,1),w,2),h,3),u,4),f,5),x,6),v,7),g,8),n,9);}int c(String...s){return~-s[0].split(s[1]).length;}String d(String s,int i,int n){for(;i-->0;s+=n);return s;}

Coba di sini.

Penjelasan umum:

Saya telah melihat kemunculan setiap karakter dalam alfabet:

E 13357789
F 45
G 8
H 38
I 5689
N 1799
O 124
R 34
S 67
T 238
U 4
V 57
W 2
X 6
  • Saya pertama kali dihitung semua kejadian dari karakter single-pertandingan: G=8; U=4; W=2; X=6.
  • Kemudian semua kejadian dari karakter dua-cocok, yang juga sesuai dengan salah satu dari empat di atas, yang saya dapat mengurangi dari jumlah mereka: F=5; H=3.
  • Kemudian saya melakukan hal yang sama lagi untuk V=7(dengan mengurangi F=5).
  • Kemudian sama untuk semua tiga pertandingan karakter yang tersisa: O=1; N=9.
    • Tetapi karena Nmemiliki dua kejadian NINE, saya harus melakukan tambahan -1untuk setiap kejadian N, jadi saya menggunakan I=9sebagai gantinya (dengan mengurangi tiga pertandingan sebelumnya, bukan dua).

Penjelasan Kode:

s->{                    // Method with String as parameter and return-type
  int g=c(s+=" ","G"),  //  Amount of 8s (and append a space to `s` first, for the .split)
      u=c(s,"U"),       //  Amount of 4s
      w=c(s,"W"),       //  Amount of 2s
      x=c(s,"X"),       //  Amount of 6s
      f=c(s,"F")-u,     //  Amount of 5s
      h=c(s,"H")-g,     //  Amount of 3s
      v=c(s,"V")-f,     //  Amount of 7s
      o=c(s,"O")-u-w,   //  Amount of 1s
      i=c(s,"I")-f-x-g; //  Amount of 9s
  return d(             //  Return the result by:
   s=d(
    s=d(
     s=d(
      s=d(
       s=d(
        s=d(
         s=d(
          s=d("",       //   Making the input String `s` empty, since we no longer need it
                 o,1),  //   Append all 1s to `s`
         w,2),          //   Append all 2s to `s`
        h,3),           //   Append all 3s to `s`
       u,4),            //   Append all 4s to `s`
      f,5),             //   Append all 5s to `s`
     x,6),              //   Append all 6s to `s`
    v,7),               //   Append all 7s to `s`
   g,8),                //   Append all 8s to `s`
  i,9);                 //   And then returning `s` + all 9s
}                       // End of method

int c(String...s){  // Separate method with String-varargs parameter and int return-type
                    //  `s[0]` is the input-String
                    //  `s[1]` is the character to check
  return~-s[0].split(s[1]).length;
                    //  Return the amount of times the character occurs in the String
}                   // End of separated method (1)

String d(String s,int i,int n){
               // Separate method with String and two int parameters and String return-type
  for(;i-->0;  //  Loop from the first integer-input down to 0
      s+=n     //   And append the input-String with the second input-integer
  );           //  End of loop
  return s;    //  Return the resulting String
}              // End of separated method (2)

1
Sial, saya akan berpikir bahwa menambahkan ke daftar lalu menyortirnya akan lebih pendek (bukan). Sudah selesai dilakukan dengan baik!
Olivier Grégoire

1
Nah, pada akhirnya, saya mengalahkan Anda , tetapi tidak banyak;)
Olivier Grégoire

2

Perl 5 , 100 byte

Kode 99 byte + 1 byte untuk -nsakelar.

${$_}++for/./g;@a=($O-$W-$U,$W,$H-$G,$U,$F-$U,$X,$S-$X,$G,$I-$F+$U-$X-$G);print$_ x$a[$_-1]for 1..9

Cobalah online!


1

Python 3 , 225 byte

def f(s):
	r=[]
	for i,w in zip([2,4,6,8,3,5,7,1,9],["WTO","UFOR","XSI","GEIHT","HTREE","FIVE","VSEEN","ONE","NINE"]):
		while s.count(w[0]):
			r+=[i]
			for l in w:s="".join(s.split(l,1))
	return "".join(sorted(map(str,r)))

Cobalah online!

Langsung: hapus digit yang diidentifikasi dengan huruf tertentu terlebih dahulu.


1

Python 3 , 125 byte

lambda s:''.join(min(w)*(2*sum(map(s.count,w[:2]))-sum(map(s.count,w)))for w in"O1WU W2 H3G U4 F5U X6 S7X G8 IUFXG9".split())

Cobalah online!

Setelah membaca tantangan terkait saya menyadari ini adalah variasi pada solusi Python mdahmoune , yang itu sendiri didasarkan pada solusi ES6 Draco18s , tapi hei, setidaknya kita dua byte.

Seperti solusi itu, kami menghitung jawabannya melalui kombinasi linear dari jumlah kemunculan huruf-huruf tertentu. Kami menyandikan kombinasi linear secara singkat dengan menuliskannya sebagai kata-kata di mana dua huruf pertama akan ditambahkan dan semuanya sesudahnya harus dikurangi. Terkadang diperlukan karakter untuk mengisi dua karakter pertama; kami menggunakan ini untuk menyembunyikan angka yang ingin kami hasilkan (yang tidak akan pernah terjadi di input, jadi tidak akan memengaruhi algoritme kami), yang kami ekstrak min.


1

R, 154

u=utf8ToInt(s)-71
m=sum
b=m(u==16)
d=m(u==14)
f=m(u==17)
a=m(u==8)-b-d
g=m(u==12)-f
cat(rep(1:9,c(a,b,m(u==11)-d,d,m(u==15)-g,f,g,m(!u),(m(u==7)-a-g)/2)))

Cobalah online!


1

Aksioma, 351 byte

s:="GXUWRFVIONETHS";e:EqTable(CHAR,INT):=table();v:=[8,6,4,2,3,5,7,9,1];z:=[k for k in 1..46|prime?(k)];F(x,y)==>for i in 1..#x repeat y;F(z,e.(s.i):=z.i);t:=[1787026,2451,16445,5957,16036207,130169,20372239,495349,20677];h(a)==(r:=1;F(a,r:=r*e.(a.i));j:=[];F(v,while r rem z.i=0 repeat(r:=r quo t.i;j:=cons(v.i,j)));j:=sort j;k:=0;F(j,k:=k*10+j.i);k)

ungolfed memberikan komentar

s:="GXUWRFVIONETHS" -- tutte le lettere di ONE..NINE in ordine di importanza 
e:EqTable(Character,Integer):=table()
v:=[8,6,4,2,3,5,7,9,1]              -- numeri da controllare in quell'ordine di apparizione di v
z:=[k for k in 1..46|prime?(k)]     -- 14 numeri primi da associare a s
F(x,y)==>for i in 1..#x repeat y 
F(z,e.(s.i):=z.i)                   -- riempie la tavola associando numeri primi alle lettere "GXUW..."
t:=[1787026,2451,16445,5957,16036207,130169,20372239,495349,20677]  -- prodotto di numeri primi 1787026 dovrebbe essere HEIGHT
h(a)==
     r:=1 ;F(a,r:=r*e.(a.i))        -- calcola il numero associato alla stringa a
     j:=[];F(v,while r rem z.i=0 repeat(r:=r quo t.i;j:=cons(v.i,j)));j:=sort j  -- leva il nome dei numeri che man mano trova, aggiunge a j
     k:=0 ;F(j,k:=k*10+j.i)         -- costruisce il numero decimale k, da j vettore ordinato
     k                              -- ritorna tale numero k
------------------------------------------------------
(8) -> h("IHNEVGENNEISTE")
   (8)  789
                                                    Type: PositiveInteger
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.