FizzBuzz Reverse Solver

32

Sinopsis: Dada la salida de un programa generalizado de FizzBuzz, devuelve la lista de factores y palabras utilizadas para el programa.

Descripción del desafío

Imagine un programa generalizado de FizzBuzz que toma como entrada una lista de factores y palabras para usar y el número desde el cual comenzar. Por ejemplo, si la entrada de este programa fue

3 2,Ninja 5,Bear 7,Monkey

El programa imprimir números de 3a 100, sustituyendo los números divisibles por 2con Ninja, número divisible por 5con Bear, y los números divisibles por 7con Monkey. Para números que son divisibles, entonces más de uno de esos términos, el programa concatenará las palabras, imprimiendo cosas como NinjaBearo BearMonkeyo NinjaMonkeyo NinjaBearMonkey. Aquí está la salida de esa entrada:

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

Tenga en cuenta que cada vez que el programa necesita combinar palabras, siempre pasa del número más bajo al más alto . Por lo tanto, no imprimirá algo como MonkeyBear(ya que Monkey es un número más alto que Bear).

Su programa debe tomar la salida del programa generalizado FizzBuzz como entrada , y generar la entrada dada al programa generalizado FizzBuzz. En otras palabras, escriba un "programa inverso" para el programa generalizado FizzBuzz. Por ejemplo, dado el bloque de código anterior como entrada, su programa debería salir 3 2,Ninja 5,Bear, 7,Monkey.

Hay algunas reglas que las palabras siempre seguirán:

  • Siempre será posible decir exactamente cuáles son los factores y las palabras de la entrada.
  • Cada palabra comenzará con una letra mayúscula y no contendrá ninguna otra letra mayúscula o número.
  • Cada factor es único.

Entradas y salidas de muestra

Entrada:

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

Salida:

6 6,Calvins 8,Hobbies

Entrada:

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

Salida:

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

Entrada:

DeliciousTartApplePie
DeliciousCreamPancakeStrawberry
DeliciousProfiterole
DeliciousCream
DeliciousPancake
DeliciousCreamStrawberryTart

Salida:

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

Puede obtener el código que usé para generar las entradas aquí .

Ajenjo
fuente
¿La lista siempre sube exactamente a 100?
Dennis
@Dennis Sí, el límite superior siempre es 100.
absenta
15
Es un honor estar en uno de tus ejemplos.
NinjaBearMonkey
Esta es una versión mucho mejor de su desafío que originalmente en el sandbox :)
Beta Decay
1
@NinjaBearMonkey Supongo que elegir nombres con muchas palabras en ellos nos hizo mejores ejemplos. ¡Gracias por incluirme a mí también @Pyrrha! :)
FryAmTheEggman

Respuestas:

10

Pyth, 73 bytes

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

Sin duda fue una pregunta difícil. Creo que he cubierto todos los casos límite, incluido todo en el ejemplo de @ MartinBüttner, y el ejemplo de factores sin repetición.

NinjaBearMonkey , Deliciousness

En el nivel superior, el programa primero encuentra todas las palabras cortando las cadenas alfabéticas en letras mayúsculas.

Luego, las filas se asignan a si cada cadena aparece o no en la fila, y cada posible factor se prueba para ver si produce el mismo orden. Si lo hace, el factor se agrega a una lista global, que es verificar si el factor ya estaba presente. Si aún no estaba presente, se utiliza el factor. Las cadenas se ordenan por primera aparición en la entrada, lo que desambigua el orden de las cadenas que aparecen una sola vez en la misma fila.

Después de eso, solo se trata de formatear e imprimir.

isaacg
fuente
5

Scala, 350 caracteres

(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}

no ganando ... pero buena pregunta.

resultados probados:

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
gilad hoch
fuente
4

Python 2, 366 340 331 bytes

Este programa recibe información a través de stdin.

Nuevo enfoque:

Calcule el factor de las palabras de una sola aparición por la distancia desde el final de la línea. Por ejemplo (de la última muestra): DeliciousTartApplePiePie es calcular como: [95,19,5,1][0]y Apple es: [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()))

Viejo enfoque:

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

Explicación (del antiguo enfoque):

  • En general, el programa crea una lista de número de línea y lista de palabras (p [(0, []), (1, ['Ninja']), (2, ['Bear']), ...]. Ej .
  • Para cada palabra en cada línea (comenzando desde el final de la línea):
    • Encuentre la próxima aparición de la palabra e inserte la diferencia y la palabra en un diccionario predefinido.
    • Si no se encuentra, inserte el factor más grande del número de línea (incluido él mismo) que ya no existe en el diccionario y la palabra al diccionario.
La cripta
fuente