Recrea la oración

12

Este desafío consta de dos partes. El ganador será la solución con el menor recuento total de bytes. Se debe usar el mismo lenguaje para ambos desafíos.

Parte 1:

Escriba una función o programa que tome una oración con solo palabras válidas como entrada, y genere una lista de los caracteres usados, el número de veces que se usa cada letra y el número de letras en cada una de las palabras en la oración original. La salida de este programa debe ser una entrada válida para el siguiente programa (exactamente como se emite)

Agregaré ejemplos y reglas detalladas más abajo.

Parte 2:

Escriba una función o programa que tome la salida del primer programa como entrada y use esta lista de palabras en inglés y recrea una oración con la información de la salida. La oración no tiene que ser la misma que la oración original.

Más información. reglas y restricciones:

Parte 1:

  • La primera entrada puede estar en cualquier formato adecuado, con o sin comillas, como argumento de función o desde STDIN, con o sin corchetes, etc.
  • La oración de entrada no contendrá signos de puntuación o caracteres especiales, excepto un punto / punto al final. Excepto por el símbolo de punto, todos los caracteres que están en la entrada estarán en la lista de palabras.
  • La primera letra de la oración será mayúscula, el resto será minúscula.
  • La salida de la parte 2 debe comenzar con la misma letra mayúscula que la oración original (por lo que no se recomienda convertir la entrada a minúsculas (pero está bien).
  • La salida puede estar en cualquier formato adecuado:
    • Debe ser posible copiar y pegar la salida directamente en el siguiente programa / función
    • No se pueden realizar modificaciones al copiar y pegar, toda la salida se debe copiar y pegar como un todo, no en partes.
    • Por ejemplo, puede generar un histograma de todas las letras del alfabeto, o solo las utilizadas (en general, lo que sea necesario para completar la parte 2)
    • No puede generar una lista de caracteres donde se repiten múltiples ocurrencias. Por ejemplo, The queueno se puede producir una salida: Teeehquu (3,5), debería ser algo así como: Tehqu, (1 3 1 1 2),(3 5).

Parte 2:

  • El programa / función debe aceptar la entrada exactamente como es de la parte 1 (una excepción, vea el comentario a continuación sobre tomar el nombre del archivo como entrada).
    • Si se necesitan corchetes, comillas o similares para analizar la entrada, estos deben ser parte de la salida de la parte 1.
  • La lista de palabras se puede encontrar aquí.
    • La lista de palabras se puede guardar localmente como w.txt, o se puede obtener de la url. La url solo contará como 5 bytes, por lo que no necesita un acortador de url.
    • Si el programa no puede abrir un archivo sin necesidad de leer el nombre como una entrada de STDIN (creo que esto es fue el caso de Pyth por lo menos), entonces el nombre del archivo puede ser tomado como un argumento de entrada separada.
  • La salida debe ser solo una oración (lista de palabras válidas), que termina con un punto y una nueva línea opcional.
    • La salida debe tener palabras con el mismo número de letras que la oración original en la parte 1 (en el orden correcto)
    • Todas las letras que se usaron en la oración original deben usarse en la nueva salida.
    • La oración debe comenzar con la misma letra mayúscula que la oración de entrada original y terminar con un punto.

Ambas partes:

  • Ninguna de las partes debe demorar más de 2 minutos en ejecutarse (no se acepta seleccionar palabras al azar hasta que se llegue a una solución).

Con las reglas enumeradas anteriormente, debe haber una posibilidad justa de que se reproduzca exactamente la misma oración, sin embargo, eso no es un requisito.

Ejemplos:

En los ejemplos a continuación, se muestran algunos formatos de entrada y salida diferentes. Muchos más son aceptados.

Parte 1:

Entrada:

Zulus win.

Salida tipo 1:

Z i l n s u w
1 1 1 1 1 2 1
5 3

Salida tipo 2:

(('Z',1),('i',1),('l',1),('n',1),('s',1),('u',2),('w',1)), (5,2)

Salida tipo 3:

'Zilnsuuw',[1,1,1,1,1,2,1],[5,2]

Parte 2:

Entrada: una copia exacta de la salida de la parte 1. Salida:

Zulus win.

Tenga en cuenta que se aceptan otras combinaciones de palabras siempre que comiencen con a Z, y la primera palabra tiene 5 letras y la segunda tiene 3.

El código más corto en bytes gana.

Stewie Griffin
fuente
Aquí está el commit: github.com/isaacg1/pyth/commit/…
PurkkaKoodari
@ LegionMammal978: Sí, puede hacerlo bajo las siguientes restricciones: el resultado f1que se pega f2debe contener todos los datos especificados en el desafío. Ningún dato adicional puede ser parte de la salida de f1. No se pueden "almacenar" f1datos para hacer que la información esté disponible cuando se la llama f2. f1solo puede tomar una cadena como entrada por llamada.
Stewie Griffin
1
La posibilidad de pronunciar la misma oración con más de 3 palabras es bastante mala, creo
Eumel es el
En general sí, pero hay muchos casos en los que es probable que salga la misma oración. Si su abuela está cansada de rehacer su viejo suéter, podría estar: "dejando de volver a tejer". No lo he comprobado, pero creo que tu abuela seguirá renunciando después de la parte 2. También las combinaciones de palabras más largas pueden devolver la misma oración.
Stewie Griffin
1
@StewieGriffin Puedes obtener fácilmente "Wig ... wow". de vuelta con esa oración de ejemplo.
question_asker

Respuestas:

5

LabVIEW, 166 primitivas de LabVIEW

En primer lugar, no creé 2 programas separados porque Labview hace flujo de datos, por lo que realmente no hay necesidad.

Guarda el histograma con el primer elemento = código ascii del resto de la primera letra de 1-26 por cantidad. La longitud simplemente se guarda en una matriz.

La primera palabra tiene 3 cheques, primera letra, longitud y letras disponibles en el histograma. El primer control de letras se detiene después de la primera palabra.

Compruebo el histograma decrementándolo para cada letra y comprobando si caería por debajo de 0.

Si encontré mi enésima palabra y no hay palabras que se puedan construir a partir de las letras que sobran, comenzaré a eliminar palabras del dictonario y rehaceré la enésima palabra y así sucesivamente hasta que encuentre una solución.

Esto podría o no funcionar para las oraciones que existen, ya que eso tomaría una eternidad en calcular (mi ejemplo ya tomó unos segundos).

Lo que probé

In: Zulus win.
Out: Zulus win.

In: Dovecot flagships oleander.
Out: Dolphin advocates forelegs.

In: Abash abel mammal test.
Out: Amass abbe hamlet malt.

Eumel
fuente
3

Python 2.7, 353 bytes

Desafortunadamente, no puedo probarlo con el archivo real w.txt ATM porque QPython para Android parece no poder manejar la E / S de archivo. Sin embargo, funcionó con datos que copié y pegué.

Parte 1, 76 bytes

h=lambda s:({c:s.count(c)for c in s if c.isalnum()},map(len,s[:-1].split()))

En: 'Hi there.'

Fuera: {'H':1, 'i':1, 't':1, 'h':1, 'e':2, 'r':1}, (2, 5)

entonces, una lista que contiene:

  • un hashmap con el histograma

  • una lista de recuentos de letras

Parte 2, 277 bytes

import itertools as i
m=lambda c:' '.join([s for s in i.product(*[[w for w in open('w.txt')if len(w)==length]for length in c[1]])if sorted(''.join(s))==sorted(sum([[k.lower()]*n for k,n in c[0].items()],[]))and s[0][0]==filter(str.isupper,c[0])[0].lower()][0]).capitalize()+'.'

Estoy realmente contento de haber logrado que sea 100% puro funcional. No estoy seguro si eso ayuda con el golf real, pero ciertamente entendí bien la parte de ofuscación: D Aquí hay una versión más amigable para los humanos de pt. 2 (exactamente el mismo flujo, pero con nombres de variables):

from itertools import product

def matching(counts):
  histo, word_lengths = counts
  first_letter = filter(str.isupper, histo)[0].lower()

  letters_nested = [ [char.lower()]*count for char, count in histo.items() ]
  letters = sum(letters_nested, [])

  word_options = [[word for word in open('w.txt') if len(word)==length] for length in word_lengths]

  sentences = product(*word_options)

  valid = [sentence for sentence in sentences if sorted(''.join(sentence))==sorted(letters) and sentence[0][0]==first_letter]
  return ' '.join(valid[0]).capitalize()+'.'
uryga
fuente
3

Perl, 516 504 bytes

incluye 2x +1 para -p

@l=map{length}/\w+/g;s/\w/$c{$&}++/eg;@h=map{"$_$c{$_}"}keys%c;$_="@h @l";chomp(@w=`cat w.txt`);s/([A-Z])1//;$o=$1;s/(\w)(\d)/$h{$1}=$2,''/eg;@L=/\d/g;$l=shift@L;@O=$_,s/^.//,g([@L],%h)&&last for grep{$l==length&&/^$o/i&&h(\%h,substr$_,1)}@w;$_="@O.";s/^./uc$&/e;sub g{my%g;($R,%g)=@_;my@R=@$R;if($j=shift@R){s/./$g{$&}--/eg;my@C=grep{$j==length&&h(\%g,$_)}@w;push(@O,$_),g([@R],%g)and return 1 or pop@O for@C;0}else{1}}sub h{($y,$z)=@_;my%T;$z=~s/\w/$T{$&}++/eg;$K=1;$K&=$T{$_}<=$y->{$_}for keys%T;$K}

Requiere tener w.txten formato unix ( \nterminaciones de línea). Usos catpara leer el archivo; cambiar a typepara windows.
Guarde el oneliner de arriba 534.ply ejecútelo como echo Test. | perl -p 534.pl.

Bastante grande, pero es un comienzo: muchas oportunidades de golf, pero solo quería publicarlo para que la respuesta de LabVIEW sea menos solitaria ;-). He omitido las optimizaciones para la ejecución por debajo del segundo, ahorrando más de 30 bytes.


Primer fragmento (73 bytes):

@l=map{length}/\w+/g;s/\w/$c{$&}++/eg;@h=map{"$_$c{$_}"}keys%c;$_="@h @l"

Produce un histograma y la longitud de la palabra en un formato compacto. Para la entrada Zulus win., produce una salida de tipo 2 sin el (,), que no es necesario aquí:

s1 l1 u2 Z1 w1 i1 n1 5 3

Aquí está, sin golfista:

sub i{
    $_=shift;                       # get parameter
    @l = map{length} /\w+/g;        # cound word lengths
    s/\w/$c{$&}++/eg;               # count letters in hash %c
    @h=map{"$_$c{$_}"}keys%c;       # construct letter-frequency pairs
    "@h @l"                         # implicit interpolation with $" (space) separator
}

Segundo fragmento (441 bytes)

Esta parte principal trata de E / S y el tratamiento especial de la primera letra, usando subrutinas gy hque se enumeran a continuación.

sub o {
    $_=shift;
    chomp(@w=`cat w.txt`);          # load the wordlist.

    s/([A-Z])1//; $o=$1;            # get and remove the uppercase character,
    s/(\w)(\d)/$h{$1}=$2,''/eg;     # reconstruct histogram in hash %h.
    @L=/\d/g;                       # get the word counts.

    $l = shift @L;                  # get the first word length.

    @O = $_,                        # initialize output with first word,
    s/^.//,                         # strip first char of word
    g([@L],%h) && last              # call the main algoritm and quit on success

    for grep {                      
            $l==length &&           # check length
            /^$o/i &&               # only match words starting with the uppercase char
            h(\%h,substr$_,1)       # check if the word satisfies the histogram
        } @w;                       # iterates all words (speedups removed).

    $_="@O.";                       # construct output sentence.
    s/^./uc$&/e;                    # make first char uppercase.
    $_
}

Esta función recursiva toma una copia del histograma, una copia de los recuentos de palabras restantes y la palabra actual. Si la matriz de longitud de palabra está vacía, devuelve verdadero. De lo contrario, disminuye el recuento de histograma para las letras de la palabra dada, toma la siguiente longitud de palabra y encuentra una lista de palabras adecuadas de la lista de palabras. Por cada palabra adecuada, se repite.

sub g {
    my%g;                           # local version of histogram
    ($R,%g)=@_;                     # get parameters.
    my@R=@$R;                       # dereference arrayref copy of word lengths.

    if($j=shift @R)                 # get the next word-length.
    {
        s/./$g{$&}--/eg;            # update histogram

        my @C =                     # get a list of suitable words.
        grep { $j==length && h(\%g,$_) }
        @w;

        push(@O,$_),                # append word to output
        g( [@R], %g )               # recurse.
            and return 1            # true: append word we're done.
            or pop @O               # remove word from output
        for @C                      # (for some reason the @C=grep doesn't work here)

        ;0
    } else { 1 }                    # no more words, done!
}

Y finalmente, esta subrutina recibe una palabra y el histograma de la oración. Calcula un nuevo histograma para la palabra y verifica si todas las letras no aparecen con más frecuencia de la permitida por el histograma de la oración.

# check if first histogram is within bounds of second
sub h{
    ($y,$z)=@_;
    my%T; $z =~ s/\w/$T{$&}++/eg;    # calc histogram

    $K=1;
    $K &= $T{$_} <= $y->{$_}
    for keys %T;#$_[0];
    $K
}

Puede pegar los fragmentos no protegidos ( sub i/o/g/h) en un solo archivo y agregar el siguiente código de prueba.

sub t {
    print $i=i(shift),$/,o($i),$/x2;
    %c=%h=@L=@X=@O=();
}

t "Test.";                              # Test.
t "Zulus win.";                         # Zulus win.
t "Happy solstice.";                    # Happy solstice.
t "Abash abel mammal test.";            # Abase alms embalm that.
t "Dovecot flagships oleander.";        # Dangled horoscope festival.
t 'This code requires further golfing.';# Tech deer fighting ferrous liquors.

  • Actualización 504 : guarde 12 bytes eliminando ay substrun parámetro para sub g.
Kenney
fuente
Ya veo, robando mis ejemplos! Es broma, las bromas son divertidas XD
Eumel
@Eumel Sí, eran diferentes a los tuyos, así que los incluí :-)
Kenney