Escribe un detector de haiku-w

41

Un haiku es un poema con tres líneas, con un conteo de sílabas 5/7/5 , respectivamente.

Un haiku-w es un poema con tres líneas, con un recuento de palabras 5/7/5 , respectivamente.

Reto

Escriba un programa que devuelva verdadero si la entrada es un haiku-w, y falso si no.

Una entrada de haiku-w válida debe constar de 3 líneas, separadas por una nueva línea.

  • La línea 1 debe constar de 5 palabras, cada palabra separada por un espacio.
  • La línea 2 debe constar de 7 palabras, cada palabra separada por un espacio.
  • La línea 3 debe constar de 5 palabras, cada palabra separada por un espacio.

Ejemplos

The man in the suit
is the same man from the store.
He is a cool guy.

Resultado: verdadero

Whitecaps on the bay:
A broken signboard banging
In the April wind.

Resultado: falso


Reglas

  • Este es el , por lo que gana la respuesta más corta en bytes.
  • Se aplican las lagunas de código estándar de golf. Hacer trampa está prohibido.
  • Otros valores de retorno booleanos, como 1y 0, son aceptables.
  • Una lista de longitud 3 de cadenas como entrada también es aceptable.
  • Las entradas válidas de haiku-w no deben tener espacios iniciales o finales, ni espacios múltiples que separen las palabras.
DomTheDeveloper
fuente
1
¿El haiku-w siempre contendrá 3 líneas?
Kritixi Lithos
1
Sí. Si la entrada contiene más o menos de 3 líneas, el programa debería devolver falso .
DomTheDeveloper
55
¿Habrá espacios iniciales o finales en alguna línea? ¿O múltiples espacios que separan palabras?
Greg Martin el
8
Por cierto, aclaraciones como esta son una razón principal para publicar primero las preguntas propuestas en el Sandbox . :)
Greg Martin
11
Puntos de bonificación por envíos donde el código en sí es un haiku-w.
Glorfindel

Respuestas:

25

JavaScript (ES6), 73 72 64 63 54 42 39 bytes

Gracias a Neil por guardar 13 bytes

a=>a.map(b=>b.split` `.length)=='5,7,5'

Explicación

Esta es una función de flecha gruesa que toma una serie de cadenas como argumento. Reemplaza cada línea por su número de palabras. Si es un haiku-w, aahora contiene una matriz de cinco, siete y cinco nuevamente. Como JavaScript no nos permite comparar 2 matrices al mismo tiempo, la matriz se convierte primero en una cadena y luego se compara. Esto da como resultado un valor booleano que se devuelve.

Luke
fuente
1
%y *tiene la misma precedencia, por lo que no necesita el ()s, aunque creo (d*2|5)que también podría funcionar. También puedes salirte con la tuya &, aunque creo que puedes mejorar incluso usando eso (b...).length==3>b.some(...length-...).
Neil
Gracias por el consejo sobre los paréntesis. Además, cambié mi enfoque, por lo que ya no compruebo explícitamente la longitud.
Lucas
1
Ah, en ese caso, no te molestes con el cálculo, solo úsalo a=>a.map(c=>c.split .length)=='5,7,5'.
Neil
Jeje, tienes razón. Debería haber pensado en eso ...
Lucas
Aún no necesita el +''- ==stringifica si el otro argumento es un string.
Neil
12

AWK (GNU Awk), 24, 30, 28, 20 bytes

Golfed

517253==$0=q=q NF NR

Producirá "517253" para True y una cadena vacía para False .

En awk, cualquier valor numérico distinto de cero o cualquier valor de cadena no vacío es verdadero. Cualquier otro valor (cero o la cadena nula, "") es falso

La guía del usuario de GNU Awk

Cómo funciona

Cada instrucción awk (regla) consiste en un patrón (o expresión) con una acción asociada:

pattern {action}

Awk leerá la entrada línea por línea (registro por registro) y evaluará la expresión del patrón para ver si se debe invocar una acción correspondiente.

El código anterior es una expresión (patrón) Awk independiente sin el bloque de acción, que se supone que es {print $0}en ese caso.

Debe leerse de derecha a izquierda:

q=q NF NR

Anexar un N umber de F ields (palabras) y N umber de R ecords (es decir, el número de línea de corriente), a la variable q .

De esta manera, al procesar un Haiku-w adecuado, q se establecerá en:

  • 51 - en línea # 1 (5 palabras)
  • 5172 - en línea # 2 (5 palabras + 7 palabras)
  • 517253 - en línea # 3 (5 palabras + 7 palabras + 5 palabras)

$0=q

Asigne el valor recién calculado de q a $ 0 (que contiene toda la línea / registro actual de forma predeterminada).

517253==$0

Compárelo con una "firma" para un Haiku-w adecuado (517253), si hay una coincidencia, toda la expresión se evalúa como "verdadera" y print $0se ejecuta una acción correspondiente (implícita ), enviando "517253" a stdout (Verdadero) , de lo contrario, la salida estará vacía (Falso).

Tenga en cuenta que esto reconocerá correctamente un Haiku-w, incluso si es seguido por un número arbitrario de líneas de basura, pero creo que está bien, ya que:

Una lista de longitud 3 de cadenas como entrada también es aceptable.

(es decir, podemos suponer que la entrada tiene 3 líneas de largo)

Prueba

>awk '517253==$0=q=q NF NR'<<EOF
The man in the suit
is the same man from the store.
He is a cool guy.
EOF

517253

¡Pruébelo en línea!

zepelín
fuente
2
Esto falla si la entrada consta de una línea que contiene 575 palabras, o dos líneas que contienen 57 y 5 palabras, etc.
Lynn
@ Lynn, cierto, poniendo en espera, hasta que esto se solucione.
zepelín
@ Lynn, debería arreglarse ahora
zepelín
1
Muy inteligente solución! :)
Lynn
9

Python , 42 bytes

lambda l:[s.count(' ')for s in l]==[4,6,4]

Pruébalo en línea!

Toma la entrada como una lista de líneas, con las palabras separadas por espacios individuales.

Como estamos garantizados que no habrá espacios iniciales o finales, y solo espacios individuales separarán cada palabra, podemos verificar un w-haiku simplemente contando los espacios en cada línea.

Hacemos esto en una lista de comprensión, para crear una lista de los recuentos de espacios. Si es un haiku correcto, debería verse así [4, 6, 4], así que lo comparamos con esto y devolvemos el resultado.

FlipTack
fuente
Si estás de acuerdo con que soporta solamente Python 2, puede guardar dos bytes: map(str.count,l,' ').
vaultah
8

Jalea , 10 9 bytes

ċ€⁶⁼“¥©¥‘

Pruébalo en línea!

Explicación

ċ€⁶⁼“¥©¥‘  Input: length-3 list of strings
 €         For each string
ċ ⁶          Count the number of spaces
    “¥©¥‘  Convert string to code page indices, makes [4, 6, 4]
   ⁼       Match
millas
fuente
Además ċ€⁶⁼4,6,4y ċ€⁶⁼464D¤... no puedo encontrar nada más corto, sin embargo. (Oh, usted puede darle la vuelta, también: 464D⁼ċ€⁶$)
Lynn
ċ€⁶Ḍ=464funciona bien para 8.
Jonathan Allan
En realidad, no , no lo hace , lo siento.
Jonathan Allan
7

Lote, 102 bytes

@echo off
call:c&&call:c 2||exit/b
:c
set/an=%1+5
set/ps=
for %%W in (%s%)do set/an-=1
exit/b%n%

Sale con un nivel de error distinto de cero en cuanto lee una línea con el número incorrecto de palabras.

Neil
fuente
1
...... bien mierda
tbodt
7

Mathematica, 21 bytes

{4,6,4}==Count@" "/@#&

Función sin nombre que toma una lista de listas de caracteres como entrada y regresa Trueo False. Simplemente cuenta cuántos espacios hay en cada lista de caracteres, que según las reglas del desafío se correlacionan perfectamente con el número de palabras en cada línea.

Presentación previa:

Mathematica, 31 bytes

Length/@StringSplit/@#=={5,7,5}&

Función sin nombre que toma una lista de cadenas como entrada y regresa Trueo False.

Greg Martin
fuente
6

Haskell, 34 33 bytes

f l=[sum[1|' '<-c]|c<-l]==[4,6,4]

Pruébalo en línea! .

Editar: gracias a @xnor por un byte!

nimi
fuente
Pointful es más corto: f l=[sum[1|' '<-c]|c<-l]==[4,6,4].
xnor
6

Retina , 12 bytes

M%` 
^4¶6¶4$

(hay un espacio final después de la primera línea)

Pruébalo en línea!

  • M%`  - Cuente el número de espacios en cada línea.

    • M - Modo de coincidencia: imprime el número de coincidencias.
    • % - para cada línea
    • ` - configuración separada y patrón regex
    • - Solo un espacio.
  • ^4¶6¶4$ - Debe haber 4, 6 y 4 espacios, y exactamente tres líneas.

    • coincide con las nuevas líneas. El resto es una simple expresión regular.

Imprime 1para entradas válidas, 0para inválidas.

Kobi
fuente
4

Python, 58 44 bytes

lambda h:[len(l.split())for l in h]==[5,7,5]

-14 por tbodt

sagiksp
fuente
Se le permite tomar la entrada como una lista de cadenas de longitud 3. Puede guardar los bytes gastados usando split("\n").
millas
44 bytes:lambda h:[len(l.split())for l in h]==[5,7,5]
tbodt
Alguien hace esto más corto para llegar tachado 44
Charlie
4

Pyth, 9 bytes

qj464T/R;

Un programa que toma la entrada de una lista "quoted strings"e imprimeTrue o Falsesegún corresponda

Banco de pruebas

Cómo funciona

qj464T/R;   Program. Input: Q
qj464T/R;Q  Implicit variable fill
     T      Are the base-10
 j          digits
  464       of 464
q           equal
      /     to the number
        ;   of spaces
       R    in each string
         Q  in the input?
            Implicitly print
TheBikingViking
fuente
4

Japt , 11 bytes

Ahorró muchos bytes gracias a @ETHproductions

Esto toma una matriz de tres cadenas como entrada.

®¸lÃ¥"5,7,5

Ejecútalo en línea!

Oliver
fuente
4

PowerShell , 43 bytes

"$args"-replace'\S'-match'^(    )
\1  
\1$'

Pruébalo en línea!

Explicación

Toma la entrada como una cadena separada de nueva línea.

Elimina todos los espacios que no son espacios en blanco, luego verifica que coincidan "4 espacios, nueva línea, 6 espacios, nueva línea, 4 espacios nueva línea" exactamente, utilizando una expresión regular.

El grupo de captura coincide con 4 espacios, la \1referencia inversa se refiere a eso. Las nuevas líneas están incrustadas en la cadena. Tenga en cuenta que la segunda línea de la expresión regular contiene dos espacios después de la referencia inversa.

briantista
fuente
1
¡Ese es un enfoque interesante!
Ismael Miguel
4

Pyke, 11 9 bytes

dL/uq

Pruébalo aquí!

dL/       -  map(i.count(" "), input)
        q - ^ == V
   u  -  [4, 6, 4]

Después del ubyte hay los siguientes bytes:0x03 0x04 0x06 0x04

Azul
fuente
3

J, 12 bytes

4 6 4=#@;:@>

La entrada es una lista en caja de cadenas.

Explicación

Este es un tenedor con un diente izquierdo constante. Esto comprueba el resultado del diente correcto,, #@;:@>para la igualdad con 4 6 4. El momento correcto desempaqueta cada ( >), luego ( @) convierte cada cadena en palabras ( ;:), luego ( @) toma la longitud de cada ( #).

Conor O'Brien
fuente
3

R, 48 bytes

all(stringr::str_count(scan(,"")," ")==c(4,6,4))

Lee un vector de caracteres de 3 longitudes de stdin y funciona contando el número de espacios. Para contar el número de espacios, usamos el str_countdel stringrpaquete que puede contar las ocurrencias según un patrón de expresiones regulares.

Un enfoque alternativo sin usar paquetes podría ser:

all(sapply(scan(,""),function(x)length(el(strsplit(x," "))))==c(5,7,5))
Billywob
fuente
Primera vez que he visto elantes, gracias por eso.
BLT
3

C 142 bytes

void f(){char *c;l=3;s[3]={0};while(l>0){if(*c==' ')s[l-1]++;if((*c=getchar())=='\n'){l--;}}printf("%d",(s[0]==4 && s[1]==6 && s[2]==4)?1:0);}

Versión sin golf:

void f()
{
  char *c;
  c = (char *)malloc(sizeof(char)); 
  int l=3;
  int s[3]= {0};


  while(l>0)
  {  
    if(*c==' ')
    s[l-1]++;

    if( (*c=getchar())=='\n')
    {    
      l--;
    }   
  }
  printf("%d",(s[0]==4 && s[1]==6 && s[2]==4)?1:0);
}

Devuelve 1 para 5/7/5 secuencia más 0.

Un caso de prueba positivo:

ingrese la descripción de la imagen aquí

Abel Tom
fuente
3

C ++, 357 bytes

Algo nuevo en el código de golf, pero esto es lo mejor que puedo hacer rápidamente

#include <iostream>
using namespace std;
int n(std::string s)
{
    int b = 0;
    for(char c: s)
        if(c == ' ') b++;
    cout << "C = " << b;
    return b;
}
int main()
{
    string a, b, c;
    getline(cin, a);
    getline(cin, b);
    getline(cin, c);
    if(n(a)==4 && n(b)==6 && n(c)==4)
        cout<<'1';
    else cout << '0';
    return 0;
}
Ricardo Iglesias
fuente
44
Bienvenido a PPCG! El objetivo del código golf es hacer que su código sea lo más corto posible; un buen primer paso sería eliminar todos los espacios en blanco innecesarios.
ETHproductions
3

Ruby 1.9.3

No es golf, pero es en sí un haiku-w

def haiku_w(input)
  lines = input.split("\n")
  lengths = lines.map(&:split).map(&:length)
  lengths.eql?([5,7,5])
end

o...

lines equals input split (newlines)
lengths equals lines map split map length
lengths equals five seven five?

Desafortunadamente, no funciona con espacios en blanco iniciales en ninguna línea, pero hace frente al seguimiento.

ymbirtt
fuente
2

Python 2 , 57 64 bytes

Edición corregida con la adición de 7 bytes después de los comentarios de @Dada. ¡Gracias!

i,j=input,''
for x in i():j+=`len(x.split())`+' '
i(j=='5 7 5 ')

Pruébalo en línea!

No es la respuesta más corta de Python por un largo camino, pero solo quería usar el nuevo truco que aprendí recientemente input()para mostrar la salida y guardar una printdeclaración. Toma una lista de líneas como entrada. Requiere Ctrl C (o cualquier otra pulsación de tecla) para finalizar el programa (con una excepción) en un terminal, pero funciona bien sin TIO.

ElPedro
fuente
44
Esto fallará en casos como este .
Dada
Te daré eso @Dada. Ese es un caso de prueba serio :)
ElPedro
Corregido y probado con su caso de prueba.
ElPedro
2

MATL, 16 bytes

"@Y:Ybn&h][ACA]=

La entrada es un conjunto de celdas de cadenas y devuelve un conjunto verdadero o falso .

Pruébalo en línea

Explicación

        % Implicitly grab input
"       % For each element in the cell array
@Y:Yb   % Split it on spaces
n       % Count the number of elements
&h      % Horizontally concatenate everything on the stack
[ACA]   % Create the array [5 7 5]
=       % Perform an element-wise equality
        % Implicitly display the truthy/falsey array
Suever
fuente
2

MATLAB / Octave, 38 bytes

@(x)cellfun(@(y)sum(y==32),x)==[4 6 4]

Esta solución acepta un conjunto de celdas de cadenas como entrada, cuenta el número de espacios en cada línea y luego compara el resultado con el conjunto [4 6 4]y produce un conjunto verdadero (todos los valores son 1) o falsey (cualquier valor es cero).

Demostración en línea

Suever
fuente
2

Clojure, 44 bytes

#(=(for[l %](count(filter #{\ }l)))'(4 6 4))

La entrada es una lista de cadenas. La función encuentra solo espacios y los cuenta. Esta explicación es un Haiku. :)

NikoNyrh
fuente
2

Java 7, 154 bytes

class M{public static void main(String[]a){System.out.print(a.length==3&&a[0].split(" ").length==5&a[1].split(" ").length==7&a[2].split(" ").length==5);}}

El requisito del programa y el potencial de tener menos o más de tres líneas, sin mencionar la verbosidad de Java en sí, hace que este código 'golfizado' sea bastante grande.

Sin golf:

Pruébalo aquí

class M{
  public static void main(String[] a){
    System.out.print(a.length == 3
        && a[0].split(" ").length == 5
         & a[1].split(" ").length == 7
         & a[2].split(" ").length == 5);
  }
}
Kevin Cruijssen
fuente
2

SimpleTemplate, 77 bytes

Lamentablemente, el enfoque de expresión regular es el más corto.

{@if"@^([^\s]+ ?){5}\s([^\s]+ ?){7}\s([^\s]+ ?){5}+$@"is matchesargv}{@echo1}

Requiere que el texto se proporcione como primer argumento, con líneas nuevas al estilo * NIX. Esto no funcionará con las nuevas líneas al estilo de Windows.

Sin golf:

{@if "@^([^\s]+ ?){5}\s([^\s]+ ?){7}\s([^\s]+ ?){5}+$@"is matches argv}
    {@echo 1}
{@/}

No basado en expresiones regulares, 114 byes

{@setR 1}{@eachargv asL keyK}{@php$DATA[L]=count(explode(' ',$DATA[L]))!=5+2*($DATA[K]&1)}{@set*R R,L}{@/}{@echoR}

Esto requiere que cada línea se proporcione como un argumento para la función.

Sin golf:

{@set result 1}
{@each argv as line key k}
    {@php $DATA['line'] = count(explode(' ', $DATA['line'])) != 5+2*( $DATA['k'] & 1 )}
    {@set* result result, line}
{@/}
{@echo result}
Ismael Miguel
fuente
2

Apilado, 22 bytes

[' 'eq sum]map(4 6 4)=

Toma la entrada desde la parte superior de la pila como una lista de cadenas de caracteres, como tal:

($'The man in the suit' $'is the same man from the store.' $'He is a cool guy.')

Explicación

[' 'eq sum]map(4 6 4)=
[         ]map          map the following function over each item
 ' 'eq                  vectorized equality with ' '
       sum              summed
              (4 6 4)=  is equal to (4 6 4)
Conor O'Brien
fuente
2

Java (OpenJDK) , 82 bytes

-2 bytes gracias a @ corvus_192!

s->s[0].split(" ").length==5&s[2].split(" ").length==5&s[1].split(" ").length==7

Pruébalo en línea!

Se ve tan golfable pero sin una función de mapa incorporada, no puedo encontrar una buena manera. La iteración a través de la matriz es de unos pocos bytes más, al igual que escribir una función de mapa utilizando secuencias.

La expresión lambda toma una matriz de cadenas y devuelve un booleano.

Pavel
fuente
¿Qué pasa si solo tiene dos líneas como entrada, o cuatro?
Kevin Cruijssen
@KevinCruijssen según el op, "Una lista de cadenas de longitud 3 como entrada también es aceptable". Mi programa toma una lista de líneas de longitud 3.
Pavel
Puede obtener una función de mapa si llama Arrays.stream, pero es lo suficientemente largo como para que no valga la pena usarla (especialmente si necesita importar Arrays)
Pokechu22
@ Pokechu22, sí, lo intenté, todavía terminé siendo más largo.
Pavel
Puede usar en &lugar de &&guardar dos bytes
corvus_192
2

SmileBASIC, 96 94 bytes

INPUT A$,B$,C$?C(A$,4)*C(B$,6)*C(C$,4)DEF C(S,E)WHILE""<S
INC N,POP(S)<"!
WEND
RETURN N==E
END
12Me21
fuente
1

R, 100 bytes

f<-function(a){all(sapply(a,function(x){length(grep(" ",as.list(strsplit(x,"")[[1]])))})==c(4,6,4))}

Toma como argumento una lista de cadenas de longitud 3. Probablemente no se jugará más golf ya que jugar más golf lo convierte en la respuesta de @ Billywob.

BLT
fuente