Escreva um detector de haiku-w

41

Um haiku é um poema com três linhas, com uma contagem de sílabas de 5/7/5 , respectivamente.

Um haiku-w é um poema com três linhas, com uma contagem de 5/7/5 palavras , respectivamente.

Desafio

Escreva um programa que retorne true se a entrada for um haiku-w e false se não.

Uma entrada válida do haiku-w deve consistir em 3 linhas, separadas por uma nova linha.

  • A linha 1 deve consistir em 5 palavras, cada palavra separada por um espaço.
  • A linha 2 deve consistir em 7 palavras, cada palavra separada por um espaço.
  • A linha 3 deve consistir em 5 palavras, cada palavra separada por um espaço.

Exemplos

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

Resultado: Verdadeiro

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

Resultado: Falso


Regras

  • Isso é , então a resposta mais curta em bytes vence.
  • Aplicam-se lacunas de código-golfe padrão. É proibido fazer batota.
  • Outros valores de retorno booleano, como 1e 0, são aceitáveis.
  • Também é aceitável uma lista de seqüências de comprimento 3 como entrada.
  • As entradas válidas do haiku-w não devem ter espaços à esquerda ou à direita ou vários espaços que separam as palavras.
DomTheDeveloper
fonte
11
O haiku-w sempre conterá 3 linhas?
Kritixi Lithos
11
Sim. Se a entrada contiver mais que ou menos de 3 linhas, o programa retornará false .
DomTheDeveloper 29/01
5
Alguma vez haverá espaços à esquerda ou à direita em qualquer linha? Ou vários espaços que separam as palavras?
Greg Martin
8
A propósito, esclarecimentos como esse são o principal motivo para postar perguntas propostas primeiro no Sandbox . :)
Greg Martin
11
Pontos de bônus para envios em que o código em si é um haiku-w.
Glorfindel

Respostas:

25

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

Agradecimentos a Neil por salvar 13 bytes

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

Explicação

Essa é uma função de seta gorda que aceita uma matriz de seqüências de caracteres como argumento. Ele substitui cada linha pela contagem de palavras. Se for um haiku-w, aagora contém uma matriz de cinco, sete e cinco novamente. Como o JavaScript não nos permite comparar duas matrizes ao mesmo tempo, a matriz é convertida em uma string primeiro e depois comparada. Isso resulta em um booleano retornado.

Luke
fonte
11
%e *tem a mesma precedência, então você não precisa dos ()s, embora eu ache (d*2|5)que também possa funcionar. Além disso, você pode se safar de um single &, embora eu ache que você pode melhorar isso mesmo usando (b...).length==3>b.some(...length-...).
Neil
Obrigado pela dica sobre os parênteses. Além disso, mudei minha abordagem, para não verificar explicitamente o comprimento.
Lucas
11
Ah, nesse caso, não se preocupe com o cálculo, apenas use a=>a.map(c=>c.split .length)=='5,7,5'.
Neil
Hehe, você está certo. Eu deveria ter pensado nisso ...
Lucas
Você ainda não precisa da string +''- ==se o outro argumento for uma string.
Neil
12

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

Golfe

517253==$0=q=q NF NR

Produzirá "517253" para True e uma string vazia para False .

No awk, qualquer valor numérico diferente de zero ou qualquer valor de sequência não vazio é verdadeiro. Qualquer outro valor (zero ou a cadeia nula, "") é falso

O Guia do Usuário do GNU Awk

Como funciona

Cada instrução awk (regra) consiste em um padrão (ou expressão) com uma ação associada:

pattern {action}

O Awk lerá a entrada linha por linha (registro por registro) e avaliará a expressão do padrão para ver se uma ação correspondente deve ser chamada.

O código acima é uma expressão autônoma do Awk (padrão) sem o bloco de ação, o que está implícito {print $0}nesse caso.

Deve ser lido da direita para a esquerda:

q=q NF NR

Acrescentar um N úmero de F fields (palavras) e N úmero de R ecords (isto é, o número de linha de corrente), para a variável q .

Dessa forma, ao processar um Haiku-w adequado, q será definido como:

  • 51 - na linha 1 (5 palavras)
  • 5172 - na linha # 2 (5 palavras + 7 palavras)
  • 517253 - na linha # 3 (5 palavras + 7 palavras + 5 palavras)

$0=q

Atribua o valor recém-calculado de q a $ 0 (que mantém a linha / registro atual inteira por padrão).

517253==$0

Compare com uma "assinatura" para um Haiku-w (517253) adequado, se houver uma correspondência, a expressão inteira será avaliada como "true" e uma ação correspondente (implícita print $0) será executada, enviando "517253" para stdout (True) , caso contrário, a saída estará vazia (False).

Observe que isso reconhecerá corretamente um Haiku-w, mesmo se for seguido por um número arbitrário de linhas de lixo, mas acredito que esteja bem, pois:

Também é aceitável uma lista de seqüências de comprimento 3 como entrada.

(ou seja, podemos assumir que a entrada tenha 3 linhas)

Teste

>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

Experimente Online!

zepelim
fonte
2
Isso falhará se a entrada consistir em uma linha contendo 575 palavras ou duas linhas que contenham 57 e 5 palavras, etc.
Lynn
@ Lynn, é verdade, colocando em espera, até que isso seja corrigido.
Zeppelin
@Lynn, deve ser corrigido agora
zeppelin
11
Correção muito inteligente! :)
Lynn
9

Python , 42 bytes

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

Experimente online!

Recebe a entrada como uma lista de linhas, com as palavras separadas por espaços únicos.

Como garantimos que não haverá espaços iniciais ou finais, e apenas espaços únicos separarão cada palavra, podemos verificar um w-haiku simplesmente contando os espaços em cada linha.

Fazemos isso em uma compreensão de lista, para criar uma lista das contagens de espaço. Se for um haiku correto, deve parecer [4, 6, 4], então comparamos com isso e retornamos o resultado.

FlipTack
fonte
Se você está bem com suporte para somente Python 2, você pode salvar dois bytes: map(str.count,l,' ').
vaultah
8

Geléia , 10 9 bytes

ċ€⁶⁼“¥©¥‘

Experimente online!

Explicação

ċ€⁶⁼“¥©¥‘  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
milhas
fonte
Também ċ€⁶⁼4,6,4e ċ€⁶⁼464D¤... não consigo encontrar nada mais curto, no entanto. (Oh, você pode lançá-lo, também: 464D⁼ċ€⁶$)
Lynn
ċ€⁶Ḍ=464funciona bem para 8.
Jonathan Allan
Na verdade, não, não , desculpe.
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%

Sai com nível de erro diferente de zero assim que lê uma linha com o número errado de palavras.

Neil
fonte
11
...... bem porcaria
tbodt 29/01
7

Mathematica, 21 bytes

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

Função sem nome, tendo uma lista de listas de caracteres como entrada e retorno Trueou False. Simplesmente conta quantos espaços existem em cada lista de caracteres, que segundo as regras do desafio se correlacionam perfeitamente com o número de palavras em cada linha.

Submissão anterior:

Mathematica, 31 bytes

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

Função sem nome, tendo uma lista de seqüências de caracteres como entrada e retorno Trueou False.

Greg Martin
fonte
6

Haskell, 34 33 bytes

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

Experimente online! .

Edit: obrigado a @xnor por um byte!

nimi
fonte
Cheia de oportunidade é mais curto: f l=[sum[1|' '<-c]|c<-l]==[4,6,4].
Xnor
6

Retina , 12 bytes

M%` 
^4¶6¶4$

(existe um espaço à direita após a primeira linha)

Experimente online!

  • M%`  - Conte o número de espaços em cada linha.

    • M - Modo de correspondência - imprima o número de correspondências.
    • % - para cada linha
    • ` - configuração separada e padrão regex
    • - apenas um espaço.
  • ^4¶6¶4$ - Deve haver 4, 6 e 4 espaços e exatamente três linhas.

    • corresponde a novas linhas. O resto é uma expressão regular simples.

Imprime 1para entrada válida, 0inválida.

Kobi
fonte
4

Python, 58 44 bytes

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

-14 por tbodt

sagiksp
fonte
Você tem permissão para usar a entrada como uma lista longa de 3 strings. Você pode salvar os bytes gastos usando split("\n").
milhas
44 bytes:lambda h:[len(l.split())for l in h]==[5,7,5]
tbodt
Alguém torna isso mais curto para alcançar riscado 44
Charlie
4

Perl , 26 bytes

24 bytes de código + 2 bytes para -apsinalizadores.

$m.=@F}{$_=$m==575&$.==3

Experimente online!

dada
fonte
4

Pitão, 9 bytes

qj464T/R;

Um programa que recebe a entrada de uma lista "quoted strings"e imprime Trueou Falseconforme apropriado.

Suíte de teste

Como 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
fonte
4

Japonês , 11 bytes

Economizou muitos bytes graças a @ETHproductions

Isso leva uma matriz de três strings como entrada.

®¸lÃ¥"5,7,5

Execute-o online!

Oliver
fonte
4

PowerShell , 43 bytes

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

Experimente online!

Explicação

Recebe entrada como uma sequência separada por nova linha.

Remove todo o espaço não em branco e verifica se ele corresponde exatamente a "4 espaços, nova linha, 6 espaços, nova linha, 4 espaços nova linha", usando uma regex.

O grupo de captura corresponde a 4 espaços, a \1referência anterior refere-se a isso. Novas linhas são incorporadas na sequência. Observe que a segunda linha do regex contém dois espaços após a referência anterior.

briantist
fonte
11
Essa é uma abordagem interessante!
Ismael Miguel
4

Pyke, 11 9 bytes

dL/uq

Experimente aqui!

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

Após o ubyte, existem os seguintes bytes:0x03 0x04 0x06 0x04

Azul
fonte
3

J, 12 bytes

4 6 4=#@;:@>

A entrada é uma lista em caixa de strings.

Explicação

Este é um garfo com um dente esquerdo constante. Isso verifica o resultado do dente certo,, #@;:@>para igualdade com 4 6 4. A hora certa desmarca cada ( >), depois ( @) converte cada sequência em palavras ( ;:) e depois ( @) assume o comprimento de cada ( #).

Conor O'Brien
fonte
3

R, 48 bytes

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

Lê um vetor de caracteres de três tamanhos de stdin e funciona contando o número de espaços. Para contar o número de espaços que usamos str_countdo stringrpacote, que pode contar ocorrências com base em um padrão regex.

Uma abordagem alternativa sem o uso de pacotes pode ser:

all(sapply(scan(,""),function(x)length(el(strsplit(x," "))))==c(5,7,5))
Billywob
fonte
Primeira vez que eu já vi elantes, obrigado por isso.
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);}

Versão não destruída:

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);
}

Retorna 1 para 5/7/5 da sequência 0.

Um teste positivo:

insira a descrição da imagem aqui

Abel Tom
fonte
3

C ++, 357 bytes

Tipo de código novo para o golfe, mas é o melhor que posso fazer rapidamente

#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
fonte
4
Bem-vindo ao PPCG! O objetivo do código de golfe é tornar seu código o mais curto possível; um bom primeiro passo seria remover todos os espaços em branco desnecessários.
ETHproductions
3

Ruby 1.9.3

Não é um jogador de golfe, mas é um haiku-w

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

ou...

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

Infelizmente, não funciona com espaços em branco à esquerda em nenhuma linha, mas lida com a direita.

ymbirtt
fonte
2

Python 2 , 57 64 bytes

Editar Corrigido com a adição de 7 bytes após o feedback do @Dada. Obrigado!

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

Experimente online!

Não é a resposta mais curta do Python, mas queria apenas usar o novo truque que aprendi recentemente input()para exibir a saída e salvar uma printdeclaração. Toma uma lista de linhas como entrada. Requer Ctrl C (ou qualquer outra tecla pressionada) para finalizar o programa (com exceção) em um terminal, mas funciona bem sem o TIO.

ElPedro
fonte
4
Isso falhará em casos como este .
Dada
Vou te dar isso @ Dadá. Esse é um caso de teste sério :)
ElPedro
Corrigido e testado com seu caso de teste.
ElPedro
2

MATL, 16 bytes

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

A entrada é uma matriz de células de strings e retorna uma matriz de verdade ou falsey .

Experimente Online

Explicação

        % 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
fonte
2

MATLAB / oitava, 38 bytes

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

Esta solução aceita uma matriz de células de cadeias como entrada, conta o número de espaços em cada linha e compara o resultado à matriz [4 6 4]e gera uma matriz de verdade (todos os valores são 1) ou falsey (qualquer valor é zero).

Demonstração online

Suever
fonte
2

Perl 6 , 25 bytes

{.lines».words~~(5,7,5)}
smls
fonte
2

Clojure, 44 bytes

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

Entrada é uma lista de cadeias. A função encontra apenas espaços e os conta. Esta explicação é um haiku. :)

NikoNyrh
fonte
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);}}

O requisito do programa e o potencial de ter menos ou mais de três linhas, sem mencionar muito a verbosidade do Java, faz com que esse código 'golfado' seja muito grande.

Ungolfed:

Experimente aqui.

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
fonte
2

SimpleTemplate, 77 bytes

Infelizmente, a abordagem da expressão regular é a mais curta.

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

Requer que o texto seja fornecido como o primeiro argumento, com novas linhas no estilo * NIX. Isso não funcionará com novas linhas no estilo Windows.

Ungolfed:

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

Não baseado em regex, 114 bytes

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

Isso requer que cada linha seja fornecida como argumento para a função.

Ungolfed:

{@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
fonte
2

Empilhados, 22 bytes

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

Recebe entrada da parte superior da pilha como uma lista de cadeias de caracteres, como:

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

Explicação

[' '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
fonte
2

Java (OpenJDK) , 82 bytes

-2 bytes graças a @ corvus_192!

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

Experimente online!

Parece tão fácil de jogar, mas sem uma função de mapa embutida, não consigo encontrar um bom caminho. A iteração na matriz é mais alguns bytes, assim como a escrita de uma função de mapa usando fluxos.

A expressão lambda pega uma matriz de Strings e retorna um booleano.

Pavel
fonte
E se você tiver apenas duas linhas como entrada ou quatro?
Kevin Cruijssen 30/01
@KevinCruijssen de acordo com o op, "Uma lista de 3 strings como entrada também é aceitável". Meu programa leva uma lista de linhas com três comprimentos.
Pavel
Você poderia ter uma função de mapa se você chamou Arrays.stream, mas isso é tempo suficiente para que ele não pode valer a pena usar (especialmente se você precisar de importação Arrays)
Pokechu22
@ Pokechu22 sim, eu tentei isso, ainda acabou sendo mais longo.
Pavel
Você pode usar em &vez de &&salvar dois 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
fonte
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 uma lista de seqüências de caracteres de comprimento 3. Provavelmente não será mais jogado, já que o golfe o transforma na resposta de @ Billywob.

BLT
fonte