Risolutore inverso FizzBuzz


32

Sinossi: dato l'output di un programma FizzBuzz generalizzato, restituisce l'elenco di fattori e parole utilizzati per il programma.

Descrizione della sfida

Immagina un programma FizzBuzz generalizzato che includa come input un elenco di fattori e parole da utilizzare e il numero da cui iniziare. Ad esempio, se l'input di questo programma era

3 2,Ninja 5,Bear 7,Monkey

Il programma stampa i numeri da 3a 100, sostituendo i numeri divisibili per 2con Ninja, i numeri divisibili per 5con Beare i numeri divisibili per 7con Monkey. Per i numeri che sono divisibili quindi più di uno di questi termini, il programma concatenerà le parole, stampando cose come NinjaBearo BearMonkeyo NinjaMonkeyo NinjaBearMonkey. Ecco l'output di quell'input:

3
Ninja
Bear
Ninja
Monkey
Ninja
9
NinjaBear
11
Ninja
13
NinjaMonkey
Bear
Ninja
17
Ninja
19
NinjaBear
Monkey
Ninja
23
Ninja
Bear
Ninja
27
NinjaMonkey
29
NinjaBear
31
Ninja
33
Ninja
BearMonkey
Ninja
37
Ninja
39
NinjaBear
41
NinjaMonkey
43
Ninja
Bear
Ninja
47
Ninja
Monkey
NinjaBear
51
Ninja
53
Ninja
Bear
NinjaMonkey
57
Ninja
59
NinjaBear
61
Ninja
Monkey
Ninja
Bear
Ninja
67
Ninja
69
NinjaBearMonkey
71
Ninja
73
Ninja
Bear
Ninja
Monkey
Ninja
79
NinjaBear
81
Ninja
83
NinjaMonkey
Bear
Ninja
87
Ninja
89
NinjaBear
Monkey
Ninja
93
Ninja
Bear
Ninja
97
NinjaMonkey
99
NinjaBear

Si noti che ogni volta che il programma deve combinare parole insieme, passa sempre dal numero più basso al numero più alto . Quindi non stamperà qualcosa del genere MonkeyBear(dal momento che Monkey è un numero più alto di Bear).

Il programma dovrebbe includere l' output del programma FizzBuzz generalizzato come input e produrre l' input fornito al programma FizzBuzz generalizzato. In altre parole, scrivere un "programma inverso" per il programma FizzBuzz generalizzato. Ad esempio, dato il blocco di codice sopra come input, il tuo programma dovrebbe produrre 3 2,Ninja 5,Bear, 7,Monkey.

Ci sono alcune regole che le parole seguiranno sempre:

  • Sarà sempre possibile dire esattamente quali sono i fattori e le parole dall'input.
  • Ogni parola inizierà con una lettera maiuscola e non conterrà altre lettere maiuscole o numeri.
  • Ogni fattore è unico.

Ingressi e uscite di esempio

Ingresso:

Calvins
7
Hobbies
9
10
11
Calvins
13
14
15
Hobbies
17
Calvins
19
20
21
22
23
CalvinsHobbies
25
26
27
28
29
Calvins
31
Hobbies
33
34
35
Calvins
37
38
39
Hobbies
41
Calvins
43
44
45
46
47
CalvinsHobbies
49
50
51
52
53
Calvins
55
Hobbies
57
58
59
Calvins
61
62
63
Hobbies
65
Calvins
67
68
69
70
71
CalvinsHobbies
73
74
75
76
77
Calvins
79
Hobbies
81
82
83
Calvins
85
86
87
Hobbies
89
Calvins
91
92
93
94
95
CalvinsHobbies
97
98
99
100

Produzione:

6 6,Calvins 8,Hobbies

Ingresso:

FryEggman
7
Am
Fry
The
11
FryAmEggman
13
14
FryThe
Am
17
FryEggman
19
AmThe
Fry
22
23
FryAmEggman
The
26
Fry
Am
29
FryTheEggman
31
Am
Fry
34
The
FryAmEggman
37
38
Fry
AmThe
41
FryEggman
43
Am
FryThe
46
47
FryAmEggman
49
The
Fry
Am
53
FryEggman
The
Am
Fry
58
59
FryAmTheEggman
61
62
Fry
Am
The
FryEggman
67
Am
Fry
The
71
FryAmEggman
73
74
FryThe
Am
77
FryEggman
79
AmThe
Fry
82
83
FryAmEggman
The
86
Fry
Am
89
FryTheEggman
91
Am
Fry
94
The
FryAmEggman
97
98
Fry
AmThe

Produzione:

6 3,Fry 4,Am 5,The 6,Eggman

Ingresso:

DeliciousTartApplePie
DeliciousCreamPancakeStrawberry
DeliciousProfiterole
DeliciousCream
DeliciousPancake
DeliciousCreamStrawberryTart

Produzione:

95 1,Delicious 2,Cream 3,Pancake 4,Strawberry 5,Tart 19,Apple 95,Pie 97,Profiterole

Puoi ottenere il codice che ho usato per generare gli input qui .


L'elenco sale sempre esattamente a 100?
Dennis,

@Dennis Sì, il limite superiore è sempre 100.
Assenzio

15
È solo un onore essere in uno dei tuoi esempi.
NinjaBearMonkey il

Questa è una versione molto migliore della tua sfida rispetto a quella originariamente nella sandbox :)
Decadimento beta

1
@NinjaBearMonkey Suppongo che scegliere nomi con molte parole in essi ci abbia reso esempi migliori. Grazie per avermi incluso anche @Pyrrha! :)
FryAmTheEggman il

Risposte:


10

Pyth, 73 byte

jd+J-101lK.zjL\,Sm,_-F>2+_Jf}d@KTUKd{smtcdf-@dTGUdf>T\:K

È stato sicuramente difficile. Penso di aver coperto tutti i casi limite, incluso tutto nell'esempio di @ MartinBüttner e l'esempio dei fattori senza ripetizione.

NinjaBearMonkey , Deliciousness

Ad alto livello, il programma trova prima tutte le parole tagliando le stringhe alfabetiche sulle lettere maiuscole.

Quindi, le righe vengono mappate sulla presenza o meno di ogni stringa nella riga e ogni possibile fattore viene testato per vedere se produce lo stesso ordinamento. In tal caso, il fattore viene aggiunto a un elenco gobal, che viene verificato per verificare se il fattore era già presente. Se non era già presente, viene utilizzato il fattore. Le stringhe sono ordinate per prima apparizione nell'input, il che chiarisce l'ordine delle stringhe che appaiono ciascuna una sola volta nella stessa riga.

Dopodiché, è solo formattazione e stampa.


5

Scala, 350 caratteri

(s:String)⇒{def g(a:Int,b:Int):Int=if(b==0)a.abs else g(b,a%b);val(j,q)=(s.lines:\100→Map.empty[String,Int]){case(l,(n,m))⇒if(l(0).isDigit)(n-1,m)else(n-1,m++(Seq(Seq(l(0)))/:l.tail){case(x,c)⇒if(c.isUpper)Seq(c)+:x else (x(0):+c)+:x.tail}.map{t⇒val w=t.mkString;w→g(m.getOrElse(w,n),n)})};s"${j+1}"+q.map{case(k,v)=>s" $v,$k"}.toSeq.sorted.mkString}

non vincente ... ma bella domanda.

risultati testati:

scala> (s:String)⇒{def g(a:Int,b:Int):Int=if(b==0)a.abs else g(b,a%b);val(j,q)=(s.lines:\100→Map.empty[String,Int]){case(l,(n,m))⇒if(l(0).isDigit)(n-1,m)else(n-1,m++(Seq(Seq(l(0)))/:l.tail){case(x,c)⇒if(c.isUpper)Seq(c)+:x else (x(0):+c)+:x.tail}.map{t⇒val w=t.mkString;w→g(m.getOrElse(w,n),n)})};s"${j+1}"+q.map{case(k,v)=>s" $v,$k"}.toSeq.sorted.mkString}
res0: String => String = <function1>

scala> res0("""DeliciousTartApplePie
     | DeliciousCreamPancakeStrawberry
     | DeliciousProfiterole
     | DeliciousCream
     | DeliciousPancake
     | DeliciousCreamStrawberryTart""")
res1: String = 95 1,Delicious 2,Cream 3,Pancake 4,Strawberry 5,Tart 95,Apple 95,Pie 97,Profiterole

scala> res0("""FryEggman
     | 7
     | Am
     | Fry
     | The
     | 11
     | FryAmEggman
     | 13
     | 14
     | FryThe
     | Am
     | 17
     | FryEggman
     | 19
     | AmThe
     | Fry
     | 22
     | 23
     | FryAmEggman
     | The
     | 26
     | Fry
     | Am
     | 29
     | FryTheEggman
     | 31
     | Am
     | Fry
     | 34
     | The
     | FryAmEggman
     | 37
     | 38
     | Fry
     | AmThe
     | 41
     | FryEggman
     | 43
     | Am
     | FryThe
     | 46
     | 47
     | FryAmEggman
     | 49
     | The
     | Fry
     | Am
     | 53
     | FryEggman
     | The
     | Am
     | Fry
     | 58
     | 59
     | FryAmTheEggman
     | 61
     | 62
     | Fry
     | Am
     | The
     | FryEggman
     | 67
     | Am
     | Fry
     | The
     | 71
     | FryAmEggman
     | 73
     | 74
     | FryThe
     | Am
     | 77
     | FryEggman
     | 79
     | AmThe
     | Fry
     | 82
     | 83
     | FryAmEggman
     | The
     | 86
     | Fry
     | Am
     | 89
     | FryTheEggman
     | 91
     | Am
     | Fry
     | 94
     | The
     | FryAmEggman
     | 97
     | 98
     | Fry
     | AmThe""")
res2: String = 6 3,Fry 4,Am 5,The 6,Eggman

4

Python 2, 366 340 331 byte

Questo programma riceve input tramite stdin.

Nuovo approccio:

Calcola il fattore delle parole di una sola occorrenza in base alla distanza dalla fine della linea. Per esempio (da l'ultimo campione): DeliciousTartApplePiePie è calcolare come: [95,19,5,1][0]e Apple è: [95,19,5,1][1].

import sys
import re
d=[(i,re.findall('[A-Z][a-z]*',l)[::-1])for i,l in enumerate(sys.stdin)]
e=101-len(d)
print e," ".join(`x`+','+`y`[1:-1]for x,y in sorted({next((j-i for j,t in d if j>i and w in t),[x for x in range(i+e,0,-1)if(i+e)%x==0][d[i][1].index(w)]):w for w,i in{w:i for i,l in d[::-1]for w in l}.items()}.iteritems()))

Vecchio approccio:

import sys
import re
l=[(i,re.findall('[A-Z][a-z]*',l))for i,l in enumerate(sys.stdin)]
e=101-len(l)
d={}
for i,s in l:
 for w in s[::-1]:
  if w not in d.values():
   d[next((j-i for j,t in l[i+1:]if w in t),next(m for m in range(i+e,0,-1)if(i+e)%m==0and m not in d))]=w 
print e," ".join(`x`+','+`y`[1:-1]for x,y in sorted(d.iteritems()))

Uso:

python FizzBuzzReverseSolver.py < Sample1.txt

Spiegazione (del vecchio approccio):

  • In generale, il programma crea un elenco di numero di riga e un elenco di parole (ad es [(0, []), (1, ['Ninja']), (2, ['Bear']), ...].
  • Per ogni parola in ogni riga (a partire dalla fine della riga):
    • Trova la ricorrenza successiva della parola e inserisci la differenza e la parola in un dizionario predefinito.
    • Se non lo trova, inserisci il più grande fattore del numero di riga (incluso se stesso) che non esiste già nel dizionario e la parola nel dizionario.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.