Utwórz łamigłówkę nonogramową

24

Nonogram to dwuwymiarowy łamigłówka logiczna, która wygląda mniej więcej tak (zrzuty ekranu z gry Pixelo , moja ulubiona gra Nonogram):

Pusta tablica z nonogramem

Celem gry jest ustalenie, jaki obraz kodują te liczby. Reguły są proste: Liczba w kolumnie lub wierszu oznacza, że ​​gdzieś w tej kolumnie lub wierszu wiele pól jest wypełnionych w jednym rzędzie. Na przykład w dolnym rzędzie na powyższym obrazku nie może być wypełnionych żadnych pól, podczas gdy w powyższym rzędzie muszą być wypełnione wszystkie jego pola. Trzeci rząd od dołu ma 8 wypełnionych pól i wszystkie będą w jednym rzędzie.

Dwie lub więcej liczb dla tej samej kolumny lub wiersza oznacza, że ​​istnieje wiele „serii” wypełnionych pól, z co najmniej jedną spacją między nimi, o tych długościach. Kolejność zostaje zachowana. Na przykład są trzy wypełnione pola w prawej kolumnie powyższego obrazu, co najmniej jedno miejsce pod nimi, a następnie jeszcze jedno wypełnione pole.

Oto ta sama zagadka, prawie ukończona:

Prawie ukończona tablica z nonogramem

(X nie są ważne, to tylko wskazówka, którą gracz pozostawia, aby powiedzieć „Ten kwadrat zdecydowanie nie jest wypełniony”. Pomyśl flagi w Saper. Nie mają one żadnych zasad.)

Mam nadzieję, że widać na przykład, że środkowe kolumny z podpowiedziami „2 2” mają dwa ciągi o długości 2 wypełnionych pól.

Twoim zadaniem, jeśli zdecydujesz się to zaakceptować, jest napisanie programu lub funkcji, która stworzy taką układankę. Rozmiar tablicy jest podawany jako pojedyncza liczba całkowita (5 <= n <= 50) na stdin lub jako argument (nie ma powodu, dla którego łamigłówka nonogramowa musi być kwadratowa, ale dla tego wyzwania będzie). Następnie otrzymasz serię 1 i 0 reprezentujących odpowiednio wypełnione i niewypełnione kwadraty na obrazie. Pierwszy n z nich to górny rząd, a następnie następny rząd itp. Zwrócisz lub wydrukujesz, aby ustawić tablicę 2 * 1 komórek (ponieważ wyglądają lepiej i daje ci miejsce na 2-cyfrowe wskazówki dla kolumny ), wszystkie są puste, z podpowiedziami odpowiadającymi danym wejściowym.

Format wyjściowy

Format wyjściowy

Próba

Wkład:

./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])

Obraz:

Pierwszy przykładowy obraz

Wydajność:

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

Wkład:

./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'

Obraz:

Drugi przykładowy obraz

Wydajność:

                   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|

Wyjaśnienia

  • Twój wynik nie musi być układanką do rozwiązania. Nie wszystkie nonogramy są rozwiązywalne, ale to nie jest twój problem. Po prostu wypisz podpowiedzi, które odpowiadają danym wejściowym, niezależnie od tego, czy stanowią dobrą łamigłówkę, czy nie.
  • Program, który pobiera argumenty z wiersza poleceń, jest dozwolony. Jest to w pewnym sensie wspomniane powyżej, ale możliwe jest, aby uzyskać zły pomysł. Po to są wyjaśnienia.
  • Drukowanie 0wiersza lub kolumny bez wypełnionych pól jest obowiązkowe. Nigdzie nie mówię tego słowami, ale jest to w przykładowych danych.
podziemny monorail
źródło
Właśnie skończyłem z moim rozwiązaniem. Czy możemy założyć, że w wierszu lub kolumnie nie będzie 3-cyfrowej liczby pól?
obrzydliwy
2
@ unikać pigeonu: 5<=n<=50jest specyfikacją, więc nie może być żadnych 3-cyfrowych liczb
Kyle Kanos
Po opublikowaniu tego pytania sam zacząłem pracować nad rozwiązaniem. Nie opublikuję go jeszcze (zgodnie z meta odpowiedzią), ale podam liczbę moich bajtów, abyście mieli coś do zrobienia: 404 bajty w Pythonie 2.7
undergroundmonorail
Czy Twój pierwszy przykładowy wynik nie zawiera więcej -niż powinien?
Ventero
@Ventro Masz rację! Wiedziałem, jak napisać program, aby to zrobić, ale do tej pory nie zrobiłem tego, więc moje próbki były ręcznie. Ups! (Zepsułem również wyjście drugiej próbki, ale naprawiłem je, zanim pojawiły się jakieś odpowiedzi.)
undergroundmonorail

Odpowiedzi:

9

GolfScript, 128 znaków

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

Dane wejściowe należy podać na STDIN jako liczby oddzielone spacjami.

Możesz przetestować przykład tutaj .

Skomentowany kod:

# 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
]\
Howard
źródło
1
+1 fajnie, nauczyłem się kilku dobrych sztuczek z tego postu
Cristian Lupascu
Udało mi się ~](:k/.zip\]{{1,%{,}%.!,+}%}/{' ':^*}%{.{,}%$-1=}:f~:r{^*\+r~)>'|'n}+%\f{.~)\[^]*@+>{^\+-2>}%}+%zip{r)^*\n}%r^*'+''--'k*n](zagrać w golfa na 123 znaki: (z jakiegoś powodu lettercount.com mówi 125 znaków, jeśli je skopiujesz, ale zapewniam cię, że to 123 znaki). Niektóre części algorytmu zostały zmienione, ale większość jest nadal taka sama. Zmieniłem także niektóre nazwy zmiennych (9 jako zmienna jest inteligentna, ale także mylące), ale możesz je zmienić, jeśli chcesz.
Zmienność
7

Ruby, 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*""+?|}

Chociaż nie daje to dokładnej próbki wyjściowej podanej w pytaniu, jest zgodne ze specyfikacjami. Jedyna różnica w przykładach polega na tym, że drukuję kilka wiodących spacji / nowych linii.

Przykład:

$ 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|

Dziennik zmian:

  • 240 -> 231: Zmieniono format wejściowy, aby zamiast argumentów standardowego używać argumentów wiersza poleceń.
  • 231 -> 230: Wyeliminowano spację, przenosząc kontrolę wartości z chunkna map.
  • 230 -> 226: Odejmij [nil]zamiast dzwonić Array#compact.
  • 226 -> 216: Uprość generowanie podpowiedzi.
Ventero
źródło
Drukujesz dodatkowe znaki nowej linii i spacje, ale do tej pory we wszystkich moich testach pasowały one do specyfikacji „0 lub więcej”, więc jesteś dobry. Ostrzegam cię teraz, chociaż, jeśli zacznę widząc liczb zmiennoprzecinkowych w powietrzu w lewo mojego monitora, będę musiał zdyskwalifikować tę odpowiedź :)
undergroundmonorail
1
@undergroundmonorail: Dane wyjściowe są drukowane w taki sposób, że length(leading spaces + numbers to the left) == 2*ni height(leading newlines + numbers at the top) == n... tak długo, jak twój monitor jest wystarczająco duży dla 3*n+1 × 2*n+2znaków, nie powinieneś dyskwalifikować mnie. :)
Ventero,
4

Ruby, 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]}*""+?|}
obolały
źródło
Jak to robisz? Próbowałem, ruby $yourprogram <<< $inputale dostałem ruby_nanograms:7:in '<main>': undefined method '+' for nil:NilClass (NoMethodError).
undergroundmonorail
@undergroundmonorail ruby nonogram.rb 2 1 0 0 1na 2x2
obrzydliwe
To dobra odpowiedź, ale nie drukujesz 0dla czwartej kolumny w drugim przykładzie.
undergroundmonorail
Właśnie zauważyłem, że +------linia ... jest wcięta również o jeden zbyt wiele spacji.
undergroundmonorail
1
@undergroundmonorail Naprawiono oba.
obrzydliwy
4

GolfScript 149 147

Kod

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

Edycje:

  • usunięto niepotrzebne miejsce
  • zdefiniowano funkcję jednoznakowego wielokrotnego użytku putsdo zapisania jeszcze jednego znaku

Dema online

Nieco adnotowana wersja kodu

# 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}/
Cristian Lupascu
źródło
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}

Bez golfa

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
}

Stosowanie

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])

Edytuj historię

1 Usunięto wyrażenie regularne używane do znajdowania kolumn. Przeciążenie
2 Prostsze jest lepsze. Dane wyjściowe do ciągu, a nie do tablicy. Usunięto funkcję pomocnika FILL (F)
3 Jeszcze łatwiej. Nie mogę nic lepszego niż to. Nadal nie można porównać do Golfscript :(

edc65
źródło
Miły. Próbowałem też wersji Javascript, ale skończyło się to na około 500 bajtach i zdecydowałem, że jestem za duży, żeby ją tutaj umieścić. Dobrze byłoby opublikować wersję bez golfa z oryginalnymi nazwami zmiennych (jeśli nadal je masz). Jak to uruchomić? Po skopiowaniu wkleję go do okna konsoli chrome otrzymuję komunikat „ReferenceError: Nieprawidłowe przypisanie lewej strony”. Czy jest coś do zmiany lub dodania przed uruchomieniem?
tigrou
@tigrou przepraszam, sintax "=>" działa tylko w Firefoksie. Zmienne: c wskazówki podpowiedzi, wymiar d, l lista danych wejściowych, o wynik, zmienna pętli i, temp.
Zi
-15 bajtów :)
nderscore
@nderscore bawiąc się kodem, mam 326. W twoim kodzie R nie jest inicjowany (łatwa pomyłka przy ponownej próbie ...)
edc65
1

R, 384 znaki

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")

Z wcięciami i niektórymi objaśnieniami:

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

Stosowanie:

> 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|
plannapus
źródło
1

C - 511

C zdecydowanie nie został stworzony do ładnego formatowania danych wyjściowych. Liczba znaków obejmuje tylko niezbędne spacje / nowe linie.

Dane wejściowe pochodzą ze STDIN, liczby oddzielone spacjami.

#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");
    }
}
Allbeert
źródło
1

Minęło kilka dni i nikt nie odpowiedział w pythonie, więc oto moja (prawdopodobnie dość kiepska) próba:

Python 2.7 - 404 397 380 bajtów

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])

Wkrótce opublikuję wersję bez golfa, ale w tej chwili uważam, że jest dość czytelna. :)

EDYCJA: Pisząc wersję bez golfa zauważyłem kilka ulepszeń, które mogłem uczynić, by były dość znaczące! Z jakiegoś powodu, którego nie potrafię wyjaśnić, ma teraz dodatkowe znaki nowej linii na górze i spacje po lewej stronie (chociaż nie sądzę, żebym zmienił cokolwiek funkcjonalnego), ale nadal spełnia specyfikację.Nadchodzi wersja bez golfa!

Nie golfowany:

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

Wprowadzono kilka zmian ze względu na czytelność ( gpodział na trzy nazwane funkcje, złożone zestawienia list w forpętle), ale logicznie działa dokładnie tak samo.

Dlatego mylące jest to, że ten nie drukuje dodatkowych spacji i znaków nowej linii, podczas gdy ten gra w golfa. ¯ \ _ (ツ) _ / ¯

podziemny monorail
źródło
1
Umm, nie mogę znaleźć twojego rozwiązania. (przepraszam, to tylko okropny żart dotyczący liczby postaci, nie przejmuj się mną :))
Klamka
@dor Aha! Spróbuj teraz żartować z kodu błędu HTTP! P
undergroundmonorail