Напишіть детектор хайку-ш


41

Хайку вірш з трьома лініями, з 5/7/5 складу рахунку, відповідно.

Хайку-ш вірш з трьома лініями, з 5/7/5 слова графа, відповідно.

Виклик

Напишіть програму, яка поверне значення true, якщо вхід є haiku-w, а false - якщо ні.

Дійсний вхід haiku-w повинен складатися з 3 рядків, розділених новим рядком.

  • Рядок 1 повинен складатися з 5 слів, кожне слово розділене пробілом.
  • Рядок 2 повинен складатися з 7 слів, кожне слово розділене пробілом.
  • Рядок 3 повинен складатися з 5 слів, кожне слово розділене пробілом.

Приклади

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

Результат: Правда

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

Результат: помилковий


Правила

  • Це , тому найкоротша відповідь у байтах виграє.
  • Діють стандартні лазівки з кодовим гольфом. Обман заборонений.
  • Інші булеві значення повернення, такі як 1і 0, є прийнятними.
  • Список рядків як довжина в якості введення також прийнятний.
  • Дійсні введення хайку-ш не повинні мати провідних чи кінцевих пробілів, або декількох пробілів, що розділяють слова.

1
Чи буде хайку-ш завжди містити 3 рядки?
Kritixi Lithos

1
Так. Якщо вхід містить більше або менше 3 рядків, програма повинна повернути помилкове значення .
DomTheDeveloper

5
Чи коли-небудь будуть провідні чи відсталі пробіли на будь-якій лінії? Або кілька пробілів, що розділяють слова?
Грег Мартін

8
До речі, подібні роз'яснення є основною причиною спочатку розміщувати запропоновані питання в « Пісочниці» . :)
Грег Мартін

11
Бонусні бали за подання, де сам код є хайку-ш.
Глорфіндель

Відповіді:


25

JavaScript (ES6), 73 72 64 63 54 42 39 байт

Завдяки Нілу за збереження 13 байт

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

Пояснення

Це жирова стрілка, яка бере аргумент рядків. Він замінює кожен рядок своїм числом слів. Якщо це хайку-ш, aтепер він містить масив із п'яти, семи та ще п’яти. Оскільки JavaScript не дозволяє нам порівнювати 2 масиви одночасно, масив перетворюється спочатку в рядок, а потім порівнюється. Це призводить до повернення булева, яка повертається.


1
%і *мають однаковий пріоритет, тож вам не потрібен ()s, хоча я думаю, що (d*2|5)це також може спрацювати. Крім того, ви можете піти з одним &, хоча я думаю, ви можете покращити навіть це, використовуючи (b...).length==3>b.some(...length-...).
Ніл

Дякуємо за пораду щодо дужок. Також я змінив свій підхід, тому я більше не явно перевіряю довжину.
Лука

1
Ага, у такому випадку, не турбуйтеся з розрахунком, просто використовуйте a=>a.map(c=>c.split .length)=='5,7,5'.
Ніл

Хе-хе, ти маєш рацію. Я мав би подумати про це ...
Лука

Ви все ще не потребуєте +''- ==stringifies, якщо інший аргумент є рядком.
Ніл

12

AWK (GNU Awk), 24, 30, 28, 20 байт

Гольф

517253==$0=q=q NF NR

Виведе "517253" для True та порожній рядок для False .

Насправді, будь-яке ненулеве числове значення або будь-яке непусте значення рядка є істинним. Будь-яке інше значення (нуль або нульовий рядок, "") - помилкове

Посібник користувача GNU Awk

Як це працює

Кожне твердження (правило) awk складається з шаблону (або виразу) із пов'язаною дією:

pattern {action}

Awk прочитає рядок введення за рядком (запис за записом) і оцінить вираз шаблону, щоб побачити, чи потрібно викликати відповідну дію.

Код вище - це окремий вираз (візерунок) Awk без блоку дій, який мається на увазі {print $0}в такому випадку.

Його слід читати справа наліво:

q=q NF NR

Приєднувати Н умбру з F ields (слова) і N умбри з R ecords (тобто номер поточного рядка), до змінного ц .

Таким чином, при обробці власного Haiku-w, q буде встановлено так:

  • 51 - на рядку №1 (5 слів)
  • 5172 - рядок №2 (5 слів + 7 слів)
  • 517253 - рядок №3 (5 слів + 7 слів + 5 слів)

$0=q

Призначте щойно обчислене значення q до $ 0 (яке за замовчуванням містить весь поточний рядок / запис).

517253==$0

Порівняйте його з "підписом" для належного Haiku-w (517253), якщо є збіг, весь вираз оцінюється як "true" і відповідна дія (неявна print $0) виконується, посилаючи "517253" в stdout (True) , інакше вихід буде порожнім (Неправдивим).

Зауважте, що це правильно розпізнає Haiku-w, навіть якщо за ним слідує довільна кількість сміттєвих ліній, але я вважаю, що це нормально, як:

Список рядків як довжина в якості введення також прийнятний.

(тобто ми можемо вважати, що вхід має три рядки)

Тест

>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

Спробуйте в Інтернеті!


2
Це не вдається, якщо вхід складається з одного рядка, що містить 575 слів, або двох рядків, що містять 57 і 5 слів, і т. Д.
Лінн

@Lynn, правда, перервану, поки це не буде виправлено.
зеппелін

@Lynn, має бути виправлено зараз
zeppelin

1
Дуже розумне виправлення! :)
Лінн

9

Пітон , 42 байти

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

Спробуйте в Інтернеті!

Вводиться як список списку рядків, при цьому слова розділені проміжками.

Оскільки ми гарантуємо, що провідних чи кінцевих пробілів не буде, і кожне слово буде відокремлено лише окремими пробілами, ми можемо перевірити w-haiku, просто підрахувавши пробіли у кожному рядку.

Ми робимо це в розумінні списку, щоб створити список відліків пробілів. Якщо це правильний хайку, він повинен виглядати так [4, 6, 4], тому ми порівнюємо його з цим і повертаємо результат.


Якщо все в порядку з підтримкою тільки Python 2, ви можете зберегти два байта: map(str.count,l,' ').
vaultah

8

Желе , 10 9 байт

ċ€⁶⁼“¥©¥‘

Спробуйте в Інтернеті!

Пояснення

ċ€⁶⁼“¥©¥‘  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

Також ċ€⁶⁼4,6,4і ċ€⁶⁼464D¤… Я не можу знайти нічого коротшого. (Ах, ви можете перевернути його, теж: 464D⁼ċ€⁶$)
Lynn

ċ€⁶Ḍ=464працює чудово для 8.
Джонатан Аллан

Насправді, ні це не так , вибачте.
Джонатан Аллан

7

Пакетна, 102 байти

@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%

Виходить із ненульової помилки, як тільки прочитає рядок із неправильною кількістю слів.


1
...... ну лайно
tbodt

7

Математика, 21 байт

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

Без імені функція приймає список списків символів в якості вхідних даних і повернення Trueабо False. Просто підраховує, скільки пробілів у кожному списку символів, які за правилами виклику ідеально співвідносяться з кількістю слів у кожному рядку.

Попереднє подання:

Математика, 31 байт

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

Без імені функція приймає список рядків в якості вхідних даних і повернення Trueабо False.



6

Сітківка , 12 байт

M%` 
^4¶6¶4$

(після першого рядка є пробіл)

Спробуйте в Інтернеті!

  • M%`  - Порахуйте кількість пробілів у кожному рядку.

    • M - Режим відповідності - друкуйте кількість збігів.
    • % - для кожного рядка
    • ` - окрема конфігурація і шаблон регулярного виразів
    • - просто пробіл.
  • ^4¶6¶4$ - Повинні бути 4, 6 і 4 пробіли, а також рівно три рядки.

    • відповідає новим рядкам. Решта - простий регулярний вираз.

Друкується 1для дійсного введення, 0для недійсного.


4

Пітон, 58 44 байти

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

-14 по tbodt


Ви можете приймати дані як список довжиною 3 рядків. Ви можете зберегти використані байти split("\n").
миль

44 байти:lambda h:[len(l.split())for l in h]==[5,7,5]
tbodt

Хтось зробить це коротшим, щоб досягти перекресленого 44
Чарлі


4

Pyth, 9 байт

qj464T/R;

Програма, яка приймає введення списку "quoted strings"та друкує Trueабо, Falseякщо це доречно.

Тестовий набір

Як це працює

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


4

PowerShell , 43 байти

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

Спробуйте в Інтернеті!

Пояснення

Приймає введення як рядок, розділений на новий рядок.

Вилучає весь непробільний простір, а потім перевіряє, чи точно він відповідає "4 пробілам, новій лінії, 6 пробілам, новій лінії, 4 пробілам новій лінії", використовуючи регулярний вираз.

Група захоплення відповідає 4 місцям, зворотній зв'язок \1посилається на це. Нові рядки вбудовані в рядок. Зверніть увагу, другий рядок регулярного вираження містить два пробіли після зворотної референції.


1
Ось цікавий заступ!
Ісмаїл Мігель


3

J, 12 байт

4 6 4=#@;:@>

Вхід є списком рядків у коробці.

Пояснення

Це виделка з постійним лівим зубцем. Це перевіряє результат правильного зубця #@;:@>, на рівність з 4 6 4. Правильний час розблоковує кожен ( >), потім ( @) перетворює кожну рядок у слова ( ;:), потім ( @) приймає довжину кожного ( #).


3

R, 48 байт

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

Читає тривимірний векторний символ із stdin та працює, рахуючи кількість пробілів. Для підрахунку кількості пробілів ми використовуємо str_countз stringrпакету, який може підраховувати події на основі шаблону регулярних виразів.

Альтернативним підходом без використання пакетів може бути:

all(sapply(scan(,""),function(x)length(el(strsplit(x," "))))==c(5,7,5))

Перший раз, коли я бачив elраніше, дякую за це.
BLT

3

C 142 байт

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

Негольована версія:

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

Повертає 1 для послідовності 5/7/5, інше 0.

Позитивний зразок:

введіть тут опис зображення


3

C ++, 357 байт

Сортування нового коду для гольфу, але це найкраще, що я міг зробити швидко

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

4
Ласкаво просимо до PPCG! Мета кодового гольфу - зробити ваш код якомога коротшим; хорошим першим кроком було б видалення всього непотрібного простору.
ETHproductions

3

Рубін 1.9.3

Не гольф, але сам по собі хайку-ш

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

або ...

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

На жаль, не працює з провідними пробілами на жодних лініях, але справляється із заднім числом.


2

Python 2 , 57 64 байт

Редагування виправлено з додаванням 7 байт після відгуку від @Dada. Дякую!

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

Спробуйте в Інтернеті!

Не найкоротший відповідь Python за довгий шлях, але просто хотів використати новий трюк, який я нещодавно дізнався, використовуючи input()для відображення результатів і збереження printзаяви. Приймає список рядків як вхідний. Потрібен Ctrl C (або будь-яке інше натискання клавіш на цю тему) для припинення програми (за винятком) в терміналі, але працює нормально без TIO.


4
Це буде терпіти невдачі в таких випадках , як цей .
Дада

Я дам вам це @Dada. Це один серйозний тестовий випадок :)
ElPedro

Виправлено та протестовано у вашому тестовому випадку.
ElPedro

2

MATL, 16 байт

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

Вхід - це масив комірок рядків і повертає масив truthy або falsey .

Спробуйте в Інтернеті

Пояснення

        % 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

2

MATLAB / Октава, 38 байт

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

Це рішення приймає масив комірок рядків як вхідний, підраховує кількість пробілів у кожному рядку, а потім порівнює результат з масивом [4 6 4]і дає масив truthy (усі значення - 1) або фальси (будь-яке значення дорівнює нулю).

Демонстрація в Інтернеті



2

Clojure, 44 байти

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

Введення - це список рядків. Функція знаходить лише пробіли і рахує їх. Це пояснення - хайку. :)


2

Java 7, 154 байти

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

Вимога програми та потенціал, що має менше чи більше трьох рядків, не надто згадуючи про багатослівність Яви, призводить до того, що цей код для гольфу стає досить великим.

Безголовки:

Спробуйте тут.

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

2

SimpleTemplate, 77 байт

На жаль, підступ до регулярного вираження найкоротший.

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

Потрібно, щоб текст наводився як перший аргумент, з * рядками у стилі NIX. Це не працюватиме з новими рядками у стилі Windows.

Безголовки:

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

На основі нерегексу, 114 байдів

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

Це вимагає, щоб кожен рядок був заданий як аргумент функції.

Безголовки:

{@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}

2

Складено, 22 байти

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

Вважає вхід у верхній частині стека як список символьних рядків як таких:

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

Пояснення

[' '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)

2

Java (OpenJDK) , 82 байти

-2 байти завдяки @ corvus_192!

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

Спробуйте в Інтернеті!

Це виглядає так поважно, але без вбудованої функції карти я не можу знайти хороший спосіб. Ітерація через масив на кілька байтів довша, як і написання функції карти за допомогою потоків.

Лямбда-вираз займає масив Strings і повертає булеву форму.


Що робити, якщо у вас є лише два рядки як вхідні, або чотири?
Кевін Кройсейсен

@KevinCruijssen згідно з оп., "Список рядків довжиною 3 як вхідний також прийнятний". Моя програма займає перелік рядків довжиною-3.
Павло

Ви можете отримати функцію карти, якщо зателефонували Arrays.stream, але це досить довго, що можливо не варто використовувати її (особливо якщо вам потрібно імпортувати Arrays)
Pokechu22

@ Pokechu22 так, я спробував це, все-таки закінчився довше.
Павло

Ви можете використовувати &замість того, &&щоб зберегти два байти
corvus_192

2

SmileBASIC, 96 94 байт

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

1

R, 100 байт

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

В якості аргументу береться список рядків довжиною 3. Можливо, далі не буде гольфу, оскільки подальший гольф перетворює це на відповідь @ Billywob.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.