Создайте пазл Nonogram


24

Nonogram является двумерным логическая головоломка , которая выглядит примерно так (скриншоты из игры Pixelo , моя любимая Nonogram игры):

Пустая доска с неграммой

Цель игры - выяснить, какое изображение кодируют эти цифры. Правила просты: число в столбце или строке означает, что где-то в этом столбце или строке столько полей заполнено в строке. Например, в нижнем ряду на изображении выше не должно быть заполненных полей, а в верхнем ряду должны быть заполнены все поля. Третий ряд снизу имеет 8 заполненных ящиков, и все они будут в ряд.

Два или более числа для одного и того же столбца или строки означают, что существует несколько «рядов» заполненных полей, с как минимум одним пробелом между этими длинами. Порядок сохранен. Например, в правом столбце вышеупомянутого изображения есть три заполненных прямоугольника, по крайней мере, один пробел под ними, а затем еще один заполненный прямоугольник.

Вот та самая загадка, почти завершенная:

Почти готовая доска с неограммой

(Икс не важны, это всего лишь подсказка, которую игрок оставляет для себя, чтобы сказать: «Этот квадрат определенно не заполнен». Подумайте о флагах в Сапер. У них нет смысла правил.)

Надеемся, что вы можете видеть, что, например, средние столбцы с подсказками, которые говорят «2 2», имеют два ряда по 2 длины, заполненные прямоугольниками.

Ваша миссия, если вы решите принять ее, - написать программу или функцию, которая создаст такую ​​головоломку. Вам дан размер доски в виде единого целого числа (5 <= n <= 50) на стандартном вводе или в качестве аргумента (нет причины, по которой головоломка с неграммой должна быть квадратной, но для этого испытания это будет). После этого вам дадут серию из 1 и 0, представляющих заполненные и незаполненные квадраты на изображении соответственно. Первые n из них - это верхний ряд, затем следующий ряд и т. Д. Вы вернете или напечатаете для вывода на доску из 2 * 1 ячеек (потому что они выглядят лучше, и это дает вам место для двухзначных подсказок для столбца ), все они пустые, с подсказками, соответствующими входным данным.

Выходной формат

Выходной формат

Образец

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

./nonogram <<< '5 0 1 1 1 0 1 1 0 1 1 1 0 1 0 1 1 1 0 1 1 0 1 1 1 0'
                                 OR
      n(5,[0,1,1,1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,1,1,0])

Образ:

Первый пример изображения

Выход:

           1
         2 1 2
       3 2 1 2 3
     +----------
    3|
  2 2|
1 1 1|
  2 2|
    3|

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

./nonogram <<< '15 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 0 1 0 1 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1'

Образ:

Второй пример изображения

Выход:

                   1                       1
                 1 1 3       3 5   5 3   3 1
                 7 2 3 2 4 2 3 210 2 3 0 4 215
               +------------------------------
              2|
              1|
              1|
              1|
              1|
            1 1|
        3 3 1 1|
        1 5 1 1|
          3 5 3|
          1 5 1|
          1 3 1|
      1 1 1 1 1|
1 1 1 1 1 1 1 1|
           11 3|
           11 3|

Разъяснения

  • Ваш вывод не должен быть решаемой загадкой. Не все нонограммы разрешимы, но это не ваша забота. Просто выведите подсказки, которые соответствуют вводу, делают ли они хорошую загадку или нет.
  • Программа, которая принимает аргументы в командной строке, разрешена. Это вроде как сказано выше, но возможно ошибиться. Вот для чего нужны разъяснения.
  • Печать 0строки или столбца без заполненных полей является обязательной. Я нигде не говорю это словами, но это в примерах.

Я почти закончил с моим решением. Можем ли мы предположить, что в строке или столбце не будет трехзначного числа блоков?
afuous

2
@voidpigeon: 5<=n<=50это спецификация, поэтому не может быть 3-значных чисел
Кайл Канос

После публикации этого вопроса я сам начал работать над решением. Я пока не буду его публиковать (согласно этому мета-ответу), но я опубликую свой счетчик байтов, чтобы у вас, ребята, было к чему стремиться: 404 байта в Python 2.7
подземный

Разве ваш первый пример вывода не содержит больше, -чем следовало бы?
Вентеро

@ Ventro Вы правы! Я знал, как написать программу для этого, но на самом деле я этого не делал до сих пор, поэтому мои примеры выходных данных были сделаны вручную. К сожалению! (Я облажался второй пример вывода, но я установил ее , прежде чем какие - либо ответы.)
undergroundmonorail

Ответы:


9

GolfScript, 128 символов

~](:k/.{{1,%{,}%.!,+}%}:^~{' ':s*}%.{,}%$-1=:9{s*\+9~)>'|'n}+%\zip^.{,~}%$0=){.~[s]*@+>{s\+-2>}%}+%zip{9)s*\n}%\[9s*'+''--'k*n]\

Ввод должен быть представлен на STDIN в виде чисел, разделенных пробелами.

Вы можете проверить пример здесь .

Код комментария:

# Parse the input into an 2D array of digits. The width is saved to variable k
~](:k/

# Apply the code block ^ to a copy of this array
.
{                # begin on code block
  {              # for each line
   1,%           #   split at 0s (1, => [0]) (leading, trailing, multiple 0s are 
                 #   removed because of operator % instead of /)
   {,}%          #   calculate the length of each run of 1s                 
   .!,+          #   special case: only zeros, i.e. []
                 #   in this case the ! operator yiels 1, thus [0], else []
  }%             # end for
}:^              # end of code block
~                # apply

# Format row headers
{' ':s*}%        # join numbers with spaces
.{,}%$-1=:9      # calulate the length of the longest row header
                 # and save it to variable <9>
{                # for each row
  s*\+           #   prepend padding spaces
  9~)>           #   and cut at length <9> from the right
  '|'n           #   append '|' and newline
}+%              # end for

# Format column headers
\zip^            # transpose input array and apply the code block ^
                 # i.e. calculate length of runs
.{,~}%$0=)       # determine (negative) length of the longest column header
{                # for each column
  .~[s]*@+       #   prepend enough spaces
  >              #   and cut at common length (from right)
  {s\+-2>}%      #   format each number/empty to 2 chars width
}+%              # end for
zip              # transpose column header into output lines
{9)s*\n}%        # prepend spaces to each line and append newline

# Inject separator line
\[
9s*              # spaces
'+'              # a plus sign
'--'k*           # k (width) number of '--'
n                # newline
]\

1
+1 хорошо, я выучил немало хороших трюков из этого поста
Кристиан Лупаску

Мне удалось ~](:k/.zip\]{{1,%{,}%.!,+}%}/{' ':^*}%{.{,}%$-1=}:f~:r{^*\+r~)>'|'n}+%\f{.~)\[^]*@+>{^\+-2>}%}+%zip{r)^*\n}%r^*'+''--'k*n](сыграть в гольф до 123 символов: (по какой-то причине на lettercount.com написано 125 символов, если вы его скопируете, но, уверяю вас, это 123 символа). Некоторые части алгоритма были изменены, но большинство остается прежним. Я также изменил некоторые имена переменных (иметь переменную 9 - это разумно, но и запутанно), но вы можете изменить их обратно, если хотите.
Волатильность

7

Руби, 216 255

n=$*.shift.to_i;k=*$*.each_slice(n)
u=->k{k.map{|i|r=i.join.scan(/1+/).map{|i|"%2d"%i.size}
[*["  "]*n,*r[0]?r:" 0"][-n,n]}}
puts u[k.transpose].transpose.map{|i|" "*(n-~n)+i*""},"  "*n+?++"--"*n,u[k].map{|i|i*""+?|}

Хотя это не дает точный пример вывода, приведенный в вопросе, он соответствует спецификациям. Единственное отличие от примеров состоит в том, что я печатаю несколько ведущих пробелов / новых строк.

Пример:

$ ruby nonogram.rb 15 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 0 1 0 1 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
# empty lines removed for brevity
                                  1                       1  
                                1 1 3       3 5   5 3   3 1  
                                7 2 3 2 4 2 3 210 2 3 0 4 215
                              +------------------------------
                             2|
                             1|
                             1|
                             1|
                             1|
                           1 1|
                       3 3 1 1|
                       1 5 1 1|
                         3 5 3|
                         1 5 1|
                         1 3 1|
                     1 1 1 1 1|
               1 1 1 1 1 1 1 1|
                          11 3|
                          11 3|

Changelog:

  • 240 -> 231: изменен формат ввода для использования аргументов командной строки вместо стандартного ввода.
  • 231 -> 230: устранение пробела путем перемещения проверки значения из chunkв map.
  • 230 -> 226: вычесть [nil]вместо звонка Array#compact.
  • 226 -> 216: Упростите генерацию подсказок.

Вы печатаете некоторые дополнительные символы новой строки и пробелы, но до сих пор во всех моих тестах они соответствовали спецификации "0 или более", так что вы хороши. Я предупреждаю вас сейчас, хотя, если я начинаю видеть число с плавающим в воздухе к левым моему монитору, я буду иметь , чтобы дисквалифицировать этот ответ :)
undergroundmonorail

1
@undergroundmonorail: Выход печатается таким образом , что length(leading spaces + numbers to the left) == 2*nи height(leading newlines + numbers at the top) == n... так до тех пор , как ваш монитор достаточно большой для 3*n+1 × 2*n+2персонажей, вы не должны дисквалифицировать меня. :)
Вентеро

4

Руби, 434

n=$*[i=0].to_i
a,b=[],[]
a.push $*.slice!(1..n)*""while $*.size>1
(b.push a.map{|c|c[i]}*"";i+=1)while i<n
a,b=*[a,b].map{|c|c.map{|d|e=d.split(/[0]+/).map(&:size).select{|f|f>i=0}.map &:to_s;(e.size>0)?e:[?0]}}
m,k=*[a,b].map{|c|c.map(&:size).max}
s="  "*m
k.times{$><<s+"  "+b.map{|c|(" "+((c.size==k-i)?(c.shift):(" ")))[-2..-1]}*"";i+=1;puts}
puts s+" "+?++?-*n*2
a.each{|c|puts"  "*(m-c.size)+" "+c.map{|d|(" "+d)[-2..-1]}*""+?|}

Как вы управляете этим? Я пытался, ruby $yourprogram <<< $inputно получил ruby_nanograms:7:in '<main>': undefined method '+' for nil:NilClass (NoMethodError).
подземный

@undergroundmonorail ruby nonogram.rb 2 1 0 0 1для 2х2
afuous

Это хороший ответ, но вы не печатаете 0четвертый-последний столбец во втором примере.
подземный

Я только что заметил, что +------... строка тоже отступает на один лишний пробел.
подземный

1
@undergroundmonorail Исправлены оба.
afuous

4

GolfScript 149 147

Код

~](:s/.zip{{[0]%{,`}%['0']or}%.{,}%$)\;:¶;{.,¶\-[' ']*\+}%}:f~¶:v;\[f~]\zip{{{.,2\-' '*\+}%''*}:d2*)' '*:z\+{puts}:o~}%z(;'+'s'-'2**++o~{d'|'+o}/

Редактирование:

  • убрано ненужное пространство
  • определил многоразовую функцию putsс одним символом для сохранения еще одного символа

Демоверсии онлайн

Несколько аннотированная версия кода

# split lines
~](:s/

# make transposed copy
.zip

#prepare numbers to show in the header
{{[0]%{,`}%['0']or}%.{,}%$)\;:¶;{.,¶\-[' ']*\+}%}:f~¶:v;

# prepare numbers to show in the left column
\[f~]\zip

#print header (vertical hints)
{  {{.,2\-' '*\+}%''*}:d~  2*)' '*:z\+puts}%

#print first line
z(;'+'s'-'2**++puts

#print horizontal hints
~{d'|'+ puts}/

4

Javascript (E6) 314 334 357 410

N=(d,l)=>{J=a=>a.join(''),M=s=>(s.match(/1+/g)||['']).map(x=>x.length),f=' '.repeat(d+1),c=[n='\n'],o=n+f+'+'+'--'.repeat(d);for(i=-1;++i<d;)c[i]=M(J(l.map((e,p)=>p%d-i?'':e))),o+=n+(f+J(M(J(l).substr(i*d,d)).map(P=n=>n>9?n:n<10?' '+n:'  '))+'|').slice(-d-2);for(;--i;)o=n+f+' '+J(c.map(e=>P(e.pop())))+o;return o}

Ungolfed

N=(d,l)=> {
  J = a => a.join(''),
  M = s => (s.match(/1+/g)||['']).map(x=>x.length),
  f=' '.repeat(d+1), c=[n='\n'], o=n+f+'+'+'--'.repeat(d);
  for(i = -1; ++i < d;)
    c[i] = M(J(l.map((e,p)=>p%d-i?'':e))),
    o += n+(f+J(M(J(l).substr(i*d,d)).map(P=n=>n>9?n:n<10?' '+n:'  '))+'|').slice(-d-2);
  for(;--i;)
    o=n+f+' '+J(c.map(e=>P(e.pop())))+o;
  return o
}

использование

N(5,[0,1,1,1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,1,1,0])

N(15,[0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,1,1,1,0,1,0,1,1,1,1,0,0,0,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1])

Редактировать историю

1 Удалено регулярное выражение, используемое для поиска столбцов. Overkill
2 Чем проще, тем лучше. Вывод в строку, а не в массив. Удалена вспомогательная функция FILL (F)
3 Еще проще. Я не могу сделать лучше, чем это. Все еще не может сравниться с Golfscript :(


Ницца. Я тоже попробовал версию Javascript, но закончил чем-то около 500 байтов и решил, что я слишком большой, чтобы разместить ее здесь. Было бы хорошо, чтобы опубликовать ungolfed версию с оригинальными именами переменных (если у вас еще есть). Кроме того, как вы управляете этим? Если я копирую, вставляю его в окно консоли chrome, я получаю «ReferenceError: Invalid left side in assignment». Есть что-то, чтобы изменить или добавить перед запуском?
Tigrou

@tigrou Извините, синтаксис "=>" работает только в Firefox. Переменные: подсказки c colunns, измерение d, l список входных данных, o выходных данных, переменная цикла i, q и z temp
edc65


@nderscore возиться с кодом, я получил 326. В вашем коде R не инициализируется (простая ошибка, когда вы пытаетесь снова и снова ...)
edc65

1

R, 384 символа

a=scan();p=function(x)paste(x,collapse="");P=paste0;s=sapply;l=length;f=function(i)lapply(apply(matrix(a[-1],nr=a,b=T),i,rle),function(x)if(any(x$v)){x$l[!!x$v]}else{0});g=function(j,i)apply(s(j,function(x)sprintf("%2s",c(rep("",max(s(j,l))-l(x)),x))),i,p);c=P(g(f(1),2),"|");d=g(f(2),1);h=p(rep(" ",nchar(c[1])-1));e=P(h,"+",p(rep("-",nchar(d[1]))));d=P(h," ",d);cat(d,e,c,sep="\n")

С отступами и некоторыми пояснениями:

a=scan() #Takes input

p=function(x)paste(x,collapse="") #Creates shortcuts
P=paste0
s=sapply
l=length

#This function finds the number of subsequent ones in a line (using rle = run length encoding).
#It takes 1 or 2 as argument (1 being row-wise, 2 column-wise
f=function(i)lapply(apply(matrix(a[-1],nr=a,b=T),i,rle),function(x)if(any(x$v)){x$l[!!x$v]}else{0})

#This function takes the result of the previous and format the strings correctly (depending if they are rows or columns)
g=function(j,i)apply(s(j,function(x)sprintf("%2s",c(rep("",max(s(j,l))-l(x)),x))),i,p)

c=paste0(g(f(1),2),"|") #Computes the rows
d=g(f(2),1) #Computes the columns
h=p(rep(" ",nchar(c[1])-1)) 
e=paste0(h,"+",p(rep("-",nchar(d[1])))) #Prepare vertical border
d=paste0(h," ",d) #Pad column indices with spaces
cat(d,e,c,sep="\n") #Prints

Использование:

> a=scan();p=function(x)paste(x,collapse="");P=paste0;s=sapply;l=length;f=function(i)lapply(apply(matrix(a[-1],nr=a,b=T),i,rle),function(x)if(any(x$v)){x$l[!!x$v]}else{0});g=function(j,i)apply(s(j,function(x)sprintf("%2s",c(rep("",max(s(j,l))-l(x)),x))),i,p);c=P(g(f(1),2),"|");d=g(f(2),1);h=p(rep(" ",nchar(c[1])-1));e=P(h,"+",p(rep("-",nchar(d[1]))));d=P(h," ",d);cat(d,e,c,sep="\n")
1: 15 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 0 1 0 0 1 0 0 0 1 1 1 1 1 0 1 0 1 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
227: 
Read 226 items
                    1                       1  
                  1 1 3       3 5   5 3   3 1  
                  7 2 3 2 4 2 3 210 2 3 0 4 215
                +------------------------------
               2|
               1|
               1|
               1|
               1|
             1 1|
         3 3 1 1|
         1 5 1 1|
           3 5 3|
           1 5 1|
           1 3 1|
       1 1 1 1 1|
 1 1 1 1 1 1 1 1|
            11 3|
            11 3|

1

С - 511

C определенно не был создан для форматирования вывода красиво. Количество символов включает только необходимые пробелы / новые строки.

Ввод из STDIN, числа разделены пробелами.

#define P printf
#define L(x) for(x=0;x<s/2+1;x++)
#define l(x) for(x=0;x<s;x++)
#define B(x,y) x[i][j]||y==s/2?P("%2d",x[i][j]):P("  ");
a[50][50],i,j,s,h[25][50],v[50][25],H[50],V[50],x[25],y[25];
main(){
    scanf("%d",&s);
    L(j)x[j]=y[j]=s/2+1;
    l(i)l(j)scanf("%d",&a[i][j]);
    for(i=s-1;i>=0;i--)
        for(j=s-1;j>=0;j--)
            a[i][j]?
                !H[j]&&(x[j]--,H[j]=1),
                h[x[j]][j]++,
                !V[i]&&(y[i]--,V[i]=1),
                v[i][y[i]]++:
            (H[j]=V[i]=0);
    L(i){
        L(j)P("  ");
        P(" ");
        l(j)B(h,i);
        P("\n");
    }
    L(i)P("  ");
    P("+");
    l(i)P("--");
    P("\n");
    l(i){
        L(j)B(v,j);
        P("|\n");
    }
}

1

Прошло несколько дней, и никто не ответил на python, так что вот моя (вероятно, довольно неудачная) попытка:

Python 2.7 - 404 397 380 байт

def p(n,m):
 k=str.join;l=[];g=lambda y:[['  ']*(max(map(len,y))-len(t))+t for t in[[' '*(a<10)+`a`for a in map(len,k("",c).split('0'))if a]or[' 0']for c in y]]
 while m:l+=[map(str,m[:n])];m=m[n:]
 x=g(l);j=k('\n',['  '*max(map(len,x))+'+'+k("",a)for a in zip(*[list(a)+['--']for a in g(zip(*l))])]);return j.replace('+',' ',j.count('+')-1)+'\n'+k('\n',[k("",a+['|'])for a in x])

В скором времени я опубликую версию без гольфа, но на данный момент я думаю, что она довольно читабельна. :)

РЕДАКТИРОВАТЬ: При написании ungolfed версии, я заметил некоторые улучшения, которые я мог сделать, чтобы это было довольно значительным! По какой-то причине, которую я не могу объяснить, теперь у него есть дополнительные символы новой строки вверху и пробелы слева (хотя я не думаю, что я что-то изменил), но он все еще соответствует спецификации.Беззвучная версия идет!

Ungolfed:

def nonogram(board_size, pixels):
    def hints(board):
        output = []
        for row in board:
            # Convert the row to a string of 1s and 0s, then get a list of strings
            # that came between two 0s.
            s = "".join(row).split('0')

            # A list of the length of each string in that list.
            l = map(len, s)

            # We now have our horizontal hints for the board, except that anywhere
            # there were two 0s consecutively we have a useless 0.
            # We can get rid of the 0s easily, but if there were no 1s in the row at
            # all we want exactly one 0.
            # Solution:
            output.append([h for h in l if h != 0] or [0])
            # In this context, `foo or bar` means `foo if foo is a truthy value, bar
            # otherwise`.
            # An empty list is falsey, so if we strip out all the strings we hardcode
            # the 0.
        return output

    def num_format(hints):
        # For both horizontal and vertical hints, we want a space before single-
        # digit numbers and no space otherwise. Convert hints to strings and add
        # spaces as necessary.
        output = []

        for row in hints:
            output.append([' '*(a < 10) + str(a) for a in row])
            # Multiplying a string by n repeats it n times, e.g. 'abc'*3=='abcabcabc'
            # The only numbers that need a space are the ones less than 10.
            # ' '*(a < 10) first evaluates a < 10 to get a True or False value.
            # Python automatically converts True to 1 and False to 0.
            # So, if a is a one digit number, we do `' '*(1) + str(a)`.
            # If it's a two digit number, we do `' '*(0) + str(a)`.
        return output

    def padding(hints):
        output = []
        longest = max(map(len, hints)) # how long is the longest row?
        for row in hints:
            output.append(['  ']*(longest - len(row)) + row)
            # Add '  ' to the beginning of every row until it's the same length
            # as the longest one. Because all hints are two characters wide, this
            # ensures all rows of hints are the same length.
        return output

    board = []

    while pixels: # non-empty list == True
        # Make a list of the first (board_size) pixels converted to strings, then
        # add that list to board. Remove those pixels from the list of pixels.
        # When pixels is empty, board has a seperate list for each row.
        board.append([str(n) for n in pixels[:board_size]])
        pixels = pixels[board_size:]

    horizontal_hints = padding(num_format(hints(board)))

    vertical_hints = padding(num_format(hints(zip(*board))))
    # zip(*l) is a common way to transpose l.
    # zip([1,2,3], [4,5,6], [7,8,9]) == [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
    # the star operator unpacks an iterable so the contents can be used as
    # multiple arguments, so
    # zip(*[[1,2,3],[4,5,6],[7,8,9]]) is the same as what we just did.
    # Transposing the board and getting the horizontal hints gives us the
    # vertical hints of the original, but transposed. We'll transpose it back,
    # but we'll also add '--' to the end of all of them to make up the line
    vertical_hints = zip(*[a + ['--'] for a in vertical_hints])

    # add n spaces, where n is the length of the longest horizontal hint, plus
    # one space to the beginning of each line in the vertical hints, then join
    # with newlines to make it all one string.
    vertical_hints = '\n'.join(['  '*max(map(len, horizontal_hints)) + '+' +
                               ''.join(a) for a in vertical_hints])

    # find the number of plus signs in the string
    # replace the first (that many - 1) plus signs with spaces
    vertical_hints = vertical_hints.replace('+', ' ', vertical_hints.count('+')-1)

    # add a pipe to each row of horizontal hints, then join it with newlines
    horizontal_hints = '\n'.join([''.join(a + ['|']) for a in horizontal_hints])

    # add and return
    return vertical_hints + '\n' + horizontal_hints

Для удобства чтения были внесены некоторые изменения ( gразделены на три именованные функции, сложный список составлен из forциклов), но логически он работает точно так же.

Вот почему это сбивает с толку, что этот не печатает лишние пробелы и переводы строк, в то время как гольф делает это. ¯ \ _ (ツ) _ / ¯


1
Хм, я не могу найти ваше решение. (извините, просто ужасная шутка относительно количества персонажей, не обращайте на меня внимания :))
Ручка двери

@дор Ага! Попробуйте сделать ваш код ошибки HTTP шутки сейчас! : P
подземный
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.