Посчитай слова пересечения

10

Рассмотрим следующую стандартную сетку кроссвордов 15 × 15 .

Сетка кроссвордов

Мы можем представить это в искусстве ASCII, используя #для блоков и (пробел) для белых квадратов.

     #    #    
     #    #    
          #    
   #   #       
###     ##   ##

     ##   #    
   #       #   
    #   ##     

##   ##     ###
       #   #   
    #          
    #    #     
    #    #     

Учитывая приведенную выше сетку кроссвордов в художественном формате ASCII, определите, сколько слов в ней содержится. (Вышеуказанная сетка состоит из 78 слов. Это, пожалуй, загадка « Нью-Йорк Таймс» в прошлый понедельник .)

Слово - это группа из двух или более последовательных пробелов, проходящих вертикально или горизонтально. Слово начинается и заканчивается либо блоком, либо краем сетки и всегда проходит сверху вниз или слева направо, а не по диагонали или назад. Обратите внимание, что слова могут охватывать всю ширину головоломки, как в шестом ряду головоломки выше. Слово не обязательно должно быть связано с другим словом.

подробности

  • На входе всегда будет прямоугольник, содержащий символы #или (пробел) со строками, разделенными символом новой строки ( \n). Вы можете предположить, что сетка состоит из любых 2 различных печатаемых символов ASCII вместо #и .
  • Вы можете предположить, что есть дополнительный завершающий перевод строки. Символы в конце пробела имеют значение, так как они влияют на количество слов.
  • Сетка не всегда будет симметричной, и это могут быть все пробелы или все блоки.
  • Ваша программа теоретически должна работать на сетке любого размера, но для этой задачи она никогда не будет больше 21 × 21.
  • Вы можете взять саму сетку в качестве ввода или имя файла, содержащего сетку.
  • Возьмите входные данные из аргументов stdin или командной строки и выведите их в stdout.
  • Если вы предпочитаете, вы можете использовать именованную функцию вместо программы, принимая сетку в качестве строкового аргумента и выводя целое число или строку через стандартный вывод или возврат функции.

Контрольные примеры

  1. Входные данные:

        #
        #
        #
    

    Вывод: 7(перед каждым есть четыре пробела #. Результат будет одинаковым, если убрать каждый числовой знак, но Markdown удаляет пробелы из пустых строк.)

  2. Входные данные:

    ##
     #
    ##
    

    Вывод: 0(Однобуквенные слова не учитываются.)

  3. Входные данные:

    ######
    #    #
      ####
    # ## #
    # ## #
    #### #
    

    Вывод: 4

  4. Вход: (10 мая, воскресенье, Нью-Йорк Таймс )

       #    ##   #       
       #    #    #       
       #         #       
           #     ###   ##
        #       #        
    ##   #   #           
            #       ##   
          #   ##         
       #        ##      #
             #   ###   ##
    #   ##         ##   #
    ##   ###   #         
    #      ##        #   
             ##   #      
       ##       #        
               #   #   ##
            #       #    
    ##   ###     #       
           #         #   
           #    #    #   
           #   ##    #   
    

    Вывод: 140

счет

Самый короткий код в байтах побеждает. Tiebreaker - самый старый пост.

NinjaBearMonkey
источник

Ответы:

7

CJam, 18 17 13 11 байт

2 байта сохранены Денисом.

Использует пробелы для заполненных ячеек и 1для пустых ячеек:

qN/_z+:~1-,

Проверьте это здесь.

объяснение

q    e# Read the entire input.
N/   e# Split into lines.
_z   e# Make a copy and transpose it.
+    e# Add the lines of the two grids together.
:~   e# Evaluate each line which will push a rep-digit number for each empty-cell chunk.
1-   e# Remove all the 1s as these correspond to individual empty cells.
,    e# Get the length of the array.
Мартин Эндер
источник
9

Slip , 18 + 3 = 21 байт

>? ( +(X|$^)<<){2}

Запустите с флагами no(отсюда +3) и используйте пробел / Xвместо пробела / #. Досадно, что это длиннее, чем у CJam / Pyth, но я думаю, что Slip не был разработан специально для игры в гольф ...

Попробуйте онлайн . Обратите внимание, что в первом примере пропущены пробелы в нескольких строках.

объяснение

>?           Optionally turn right, hence matching either horizontally or vertically
[space]      Match a space
(    ){2}    Group, twice:
[space]+       Match 1+ spaces
(X|$^)         Either an X or the boundary of the grid
<<             Reverse the match pointer by turning left twice

nВыходной флаг марка печать количества совпадений, иo флаг позволяет перекрывающихся матчи , начиная с одной и той же площади. Причина возврата туда и обратно заключается в том, что Slip пытается найти совпадения, начиная с каждого квадрата, и мы хотим убедиться, что мы сопоставляем только полную строку, а не частичную. Slip возвращает только уникальные совпадения, даже если они начинались с разных позиций.

Примечание: Первоначально у меня было >?( +(X|$^)<<){2}, с первым пробелом внутри. Это может пропустить некоторые случаи с двумя пробелами на краю, так как указатель будет выглядеть так:

XXX       XXX       XXX       XXX
X>        X >       X<        <
XXX       XXX       XXX       XXX

[sp]    [sp]+$^    <<[sp]    [sp]+   (uh oh match fails)
Sp3000
источник
Почему два флага три байта?
lirtosiast
@ThomasKwa Я думаю, что текущая политика с флагами командной строки - это мета-пост , который считает количество байтов в отличие от обычного вызова кода. Таким образом, здесь разница между py -3 slip.py regex.txt input.txtи py -3 slip.py regex.txt input.txt no, что составляет три байта (включая пространство перед n)
Sp3000
В этом есть смысл. Я думал об этом с точки зрения энтропии; иногда я забываю, что это персонажи, которых мы считаем.
lirtosiast
4

Haskell, 81 байт

import Data.List
m x=sum[1|(_:_:_)<-words x]
f x=m x+m(unlines$transpose$lines x)

Использует пробелы качестве блочных символов и любые другие (не пробельные) символы в качестве пустой ячейки.

Как это работает: разбить ввод на список слов в пробелах. Возьмите 1для каждого слова с как минимум 2 символа и суммируйте эти 1s. Примените ту же процедуру к транспозиции (разбить на \n) входных данных. Добавьте оба результата.

Ними
источник
4

JavaScript ( ES6 ) 87 121 147

Создайте транспонирование входной строки и добавьте ее к вводу, затем посчитайте строки из 2 или более пробелов.

Запустите фрагмент в Firefox для проверки.

Кредиты @IsmaelMiguel, решение для ES5 (122 байта):

function F(z){for(r=z.split(/\n/),i=0;i<r[j=0][L='length'];i++)for(z+='#';j<r[L];)z+=r[j++][i];return~-z.split(/  +/)[L]};

F=z=>
(
  r=z.split(/\n/),
  [r.map(r=>z+=r[i],z+='#')for(i in r[0])],
  ~-z.split(/  +/).length
)

// TEST
out=x=>O.innerHTML += x + '\n';

[
'     #    #    \n     #    #    \n          #    \n   #   #       \n###     ##   ##\n               \n     ##   #    \n   #       #   \n    #   ##     \n               \n##   ##     ###\n       #   #   \n    #          \n    #    #     \n    #    #     ', '##\n #\n##', '    #\n    #\n    #',
 '######\n#    #\n  ####\n# ## #\n# ## #\n#### #',
 '   #    ##   #       \n   #    #    #       \n   #         #       \n       #     ###   ##\n    #       #        \n##   #   #           \n        #       ##   \n      #   ##         \n   #        ##      #\n         #   ###   ##\n#   ##         ##   #\n##   ###   #         \n#      ##        #   \n         ##   #      \n   ##       #        \n           #   #   ##\n        #       #    \n##   ###     #       \n       #         #   \n       #    #    #   \n       #   ##    #   '  
].forEach(x=>out(x.replace(/ /g,'.')+'\n'+F(x)+'\n'))
<pre id=O></pre>

edc65
источник
1
Как насчет F=z=>{for(r=z.split(/\n/),i=0;i<r[j=0][L='length'];i++)for(z+='#';j<r[L];)z+=r[j++][i];return~-z.split(/ +/)[L]}? Это 113 байтов в длину. Ваше регулярное выражение было заменено на / +/(2 пробела), j=0было добавлено в forцикл 'parent', и вместо использования синтаксиса obj.lengthя изменил его на использование L='length'; ... obj[L], которое повторяется 3 раза.
Исмаэль Мигель
Я заставил его работать на es6fiddle.net/iakdcpdh (вместо этого F=z=>мне пришлось использовать var F=(z,i,L,j,r)=>). Я проверил его на IE11, и он работает!
Исмаэль Мигель
@ IsmaelMiguel молодец! и лучше всего подходит для ES5. Глядя на это снова, я нашел что-то более ES6ish и короче. Может быть, вы могли бы опубликовать свое решение для ES5.
edc65
Нет, все в порядке. Это было ваше решение, я просто уменьшил его. Я не нахожу справедливым ответить, как если бы это был мой собственный.
Исмаэль Мигель
Теперь, когда я думаю об этом, вы можете заменить /\n/строку шаблона реальным переводом строки между. Это экономит 1 байт, так как вам не нужно писать escape-последовательность.
Исмаэль Мигель
3

Pyth, 15 14 13 байт

lftTcjd+.zC.z

Я использую как разделитель и #как заполнение символов вместо их противоположного значения от OP. Попробуйте онлайн: демонстрация

Вместо #символа заполнения он принимает также буквы. Таким образом, вы можете взять разгаданную кроссворд и напечатать количество слов. И если вы удалите lкоманду, она даже печатает все слова. Проверьте это здесь: головоломка Sunday Times от 10 мая

объяснение

        .z      all input rows
          C.z   all input columns (C transposes)
       +        add them (all rows and columns)
     jd         join by spaces
    c           split by spaces
 f              filter for pieces T, which satisfy:
  tT              len(T) > 1
l               length, implicitly printed
Jakube
источник