Construye un juego de adivinanzas de palabras de nueve niveles

11

Los basicos:

Tendrá que proporcionar un juego de adivinanzas de palabras de nueve niveles en la menor cantidad de caracteres posible (en el idioma que elija).

Las métricas:

  • Proporcione una lista de palabras (una palabra por línea, separada por una nueva línea) (por ejemplo, /usr/share/dict/wordso similar podría hacer). Está bien canalizar un nombre de archivo o la lista de palabras en su solución.
  • Proporcione 9 niveles con longitud de palabra creciente (palabras con 4 caracteres ->12 caracteres):
Nivel 1: una palabra aleatoria de la lista de palabras que contiene 4 caracteres
Nivel 2: una palabra aleatoria de la lista de palabras que contiene 5 caracteres.
... ...
Nivel 8: una palabra aleatoria de la lista de palabras que contiene 11 caracteres.
Nivel 9: una palabra aleatoria de la lista de palabras que contiene 12 caracteres.
  • En cada nivel, ofusque una palabra elegida al azar de la lista (con una longitud de palabra específica, por supuesto) y reemplace un cierto número de caracteres por el asterisco ( *). El número de caracteres a reemplazar: current_word_length / 3(redondear hacia abajo). Aleatorice qué caracteres reemplazar.
  • Deje que el jugador "adivine" la palabra (solo una trypor nivel), dé su opinión ( correcto wrong) y dé puntos en consecuencia. Cuando es correcto, el jugador gana number_of_obfuscated_characters * 10 points.
  • Imprime el puntaje actual al final de cada nivel.

El formato (y muestra de E / S):

Asegúrese de seguir el siguiente esquema de formato:

Nivel 1 # encabezado de nivel
======= # 
g * ek # palabra ofuscada
geek # entrada del usuario
correcta # conjetura validación
puntuación: 10 # puntuación de impresión
            # #  
Nivel 2
=======
l * nux
linux
correcto
puntuación: 20

Nivel 3
=======
corrió ** m
aleatorio
correcto
puntuación: 40

...

Nivel 9
=======
sem *** act * ve
semiinactivo
incorrecto
puntuación: 90

Ganador:

La solución más corta (por recuento de caracteres de código). Diviértete jugando al golf!

ChristopheD
fuente
¿Cuál es la solución para sem ** act ve, por cierto?
Joe Z.
@JoeZ. quizás sem***act*ve==>semelfactive
dev-masih

Respuestas:

5

Perl, 180 caracteres

@w=<>;for$n(4..12){@x=grep/^.{$n}$/,@w;$_=$w=$x[rand@x];vec($_,rand$n,8)=42while($==$n/3)>y/*//;print"Level @{[$n-3]}
=======
$_";say<>eq$w?($@+=$=)&& correct:wrong,"
score: $@0
"}

¿Ruby golpeando a Perl? ¡Eso no servirá! :-)

Al igual que la solución Ruby de jsvnm, pero a diferencia del código Perl de Joel Berger, este script toma el nombre de archivo de una lista de palabras como un parámetro de línea de comando. Es decir, debe ejecutarlo así:

perl -M5.010 guessword.pl /usr/share/dict/words

Aquí hay una versión de golf:

@w = <>;
for $n (4..12) {
    @x = grep /^.{$n}$/, @w;
    $_ = $w = $x[rand@x];
    vec($_, rand $n, 8) = 42 while ($= = $n/3) > y/\*//;
    print "Level @{[ $n-3 ]}\n=======\n$_";
    say <> eq $w ? ($@ += $=) && correct : wrong, "\nscore: $@0\n"; 
}

La declaración vec($_, rand $n, 8) = 42 while ($= = $n/3) > y/*//contiene algunos trucos interesantes. Primero, 42 es el código ASCII de un asterisco; Resulta que usar vecpara modificar caracteres individuales en una cadena es más corto que hacerlo con substr. En segundo lugar, la variable $=solo toma valores enteros, por lo que usarla para almacenar la cantidad de letras ocultas me ahorra un int. Finalmente, y/*//es una forma corta de contar el número de asteriscos en una cadena usando el operador de transliteración.

Editar: guardé 7 caracteres al usar $@para almacenar el puntaje dividido entre 10 y agregarle un cero durante la salida (que, pensándolo bien, habría sido más corto que la versión anterior, incluso si hubiera usado una variable normal) .

Edición 2: resulta que la incrustación de nuevas líneas literales en las cadenas de salida ahorra un char sobre el enredo $,.

Ilmari Karonen
fuente
5

Rubí (188)

toma el nombre del archivo para leer palabras como argumento.

q=*$<
s=0
4.upto(12){|n|o=''+w=q.grep(/^#{?.*n}$/).sample
[*0..n-1].sample(c=n/3).map{|i|o[i]=?*}
puts"Level #{n-3}",?=*7,o
puts STDIN.gets==w ?(s+=c;"correct"):"wrong","score: #{s}0",""}
jsvnm
fuente
Bonito (Ruby venció a Perl, ese no es un evento familiar en Code Golf ;-)
ChristopheD
En mi defensa no intenté tanto. Me alegro de que Ilmari Karonen me respaldara.
Joel Berger
3

Bash, 350 caracteres

S=0
for L in {4..12}
do
echo -e Level $(($L-3))\\n=======
W=$(grep -E ^.{$L}$ /usr/share/dict/words|shuf|tail -1)
G=$W
while [ `sed 's/[^*]//g'<<<$G|wc -c` -le $(($L/3)) ]
do
P=$(bc<<<$RANDOM*$L/32767)
G=$(sed "s/\(.\{$P\}\)./\1*/"<<<$G)
done
echo $G
read U
if [ x$U == x$W ]
then
echo correct
S=$(($S+$L/3*10))
else
echo wrong
fi
echo score: $S
done
ninjalj
fuente
No hacer trampa! Son 371 caracteres según Notepad ++.
nyuszika7h
66
@ Nyuszika7H: incluyendo 21 caracteres, ¿no? Esto es para Unix, donde una nueva línea es un carácter de salto de línea único.
ninjalj
@ninjalj: Sí, pero ten en cuenta que no todos usan el formato de salto de línea Unix. Tenemos que ser justos. meta.codegolf.stackexchange.com/questions/167/…
nyuszika7h
10
@ Nyuszika7H: Si puedes usarlo, entonces debes hacerlo en un código de golf. Si su idioma tiene dos formas equivalentes de hacer algo y una es más corta, ¿usa la más larga porque algunas personas podrían no conocer la más corta? En cuanto a los saltos de línea, si tiene un idioma que requiere CRLF, entonces no tiene suerte, pero no conozco ese idioma.
Joey
1
¿No puede reemplazar casi siempre las nuevas líneas con punto y coma o espacios?
barrycarter
2

Perl: 266

@ARGV='/usr/share/dict/words';@w=<>;$"='';while($l<9){$o=1+int++$l/3;@s=grep{$l+4==length}@w;@g=split//,$t=$s[rand$#s+1];my%r;$r{rand$#g}++while keys%r<$o;$g[$_]='*'for keys%r;print"Level $l\n=======\n@g";print<>eq$t?do{$p+=$o*10;"Correct"}:"Wrong","\nScore: $p\n"}

o con un poco más de espacio en blanco

@ARGV='/usr/share/dict/words';
@w=<>;
$"='';
while($l<9){
  $o=1+int++$l/3;
  @s=grep{$l+4==length}@w;
  @g=split//,$t=$s[rand$#s+1];
  my%r;
  $r{rand$#g}++while keys%r<$o;
  $g[$_]='*'for keys%r;
  print"Level $l\n=======\n@g";
  print<>eq$t?do{$p+=$o*10;"Correct"}:"Wrong","\nScore: $p\n"
}

¡y creo que con un poco de trabajo podría mejorar!

Joel Berger
fuente
2

R, 363 caracteres

w=tolower(scan("/usr/share/dict/words",what="c"));l=nchar(w);score=0;for(i in 1:9){mw=sample(w[l==i+3],1);cat("Level",i,"\n=======\n",replace(strsplit(mw,"")[[1]],sample(nchar(mw),floor(nchar(mw)/3)),"*"),"\n");v=scan(what="c",n=1,quiet=T);if(length(v)!=0&&v==mw){score=score+10*floor(nchar(mw)/3);cat("correct\n")} else cat("wrong\n");cat("score:",score,"\n\n")}
Paolo
fuente
2

Python 335

Sé que llego un poco tarde a la fiesta, pero Python no está representado, así que pensé qué diablos:

import sys
import random
D=open(sys.argv[1]).read().split()
random.shuffle(D)
z=0
for L in range(1,10):
 M=L+3;N=M/3;w=[c for c in D if len(c)==M][0];U=list(w)
 for i in[random.randint(0,M-1)for i in range(N)]:U[i]='*'
 print"\nLevel %d\n=======\n"%L+''.join(U);k=raw_input()==w;z+=[0,N*10][k];print["wrong","correct"][k]+"\nscore:",z

Y semi-sin golf:

import sys
import random
words = open(sys.argv[1]).read().split()
random.shuffle(words)
score=0
for L in range(1,10):
   M=L+3
   N=M/3
   w=[c for c in words if len(c)==M][0]
   obfus=list(w)
   for i in [random.randint(0,M-1) for i in range(N)]: obfus[i]='*'
   obfus=''.join(obfus)
   print"\nLevel %d\n=======\n"%L+obfus
   correct=raw_input()==w
   score+=[0,N*10][correct]
   print["wrong","correct"][correct]+"\nscore:",score
Gordon Bailey
fuente
2

K, 198

Asume un diccionario d en el directorio de trabajo actual.

{O:{@[x;(-_c%3)?c:#x;:;"*"]}',/W:{1?x@&y=#:'x}[_0:`d]'4+!9;i:1+S:0;while[#O;-1"Level ",$i;-1"=======";-1@*O;$[(**W)~0:0;[-1"correct";S+:10*+/"*"=*O];-1"wrong"];-1"score: ",$S;-1"";W:1_W;O:1_O;i+:1]}

Sin golf:

{
        /W = wordlist; O = obfuscated
        O:{@[x;(-_c%3)?c:#x;:;"*"]}',/W:{1?x@&y=#:'x}[_0:`d]'4+!9;     
        i:1+S:0;                            
        while[#O;
                -1"Level ",$i;
                -1"=======";
                -1@*O;
                $[(**W)~0:0;              /Read user input and compare to the first word
                        [-1"correct";
                        S+:10*+/"*"=*O];  /if correct, increment score
                        -1"wrong"];
                -1"score: ",$S;
                -1"";
                W:1_W;                    /knock one off the top of both word lists
                O:1_O;
                i+:1]
}
tmartin
fuente