Подтвердить что ты не робот

Code Golf: проверить сетку Sudoku

Введение

Действительная сетка Sudoku заполняется цифрами от 1 до 9, причем число не встречается более одного раза в каждом подблоке из 9, строки или столбца. Прочтите эту статью для получения более подробной информации, если вы не знакомы с этой популярной загадкой.

Вызов

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

Ввод будет состоять из 9 строк по 9 символов, представляющих сетку. Пустая ячейка будет представлена ​​символом .. Ваш выход должен быть Valid, если сетка действительна, иначе вывести Invalid.

Пример

Ввод

123...789
...456...
456...123
789...456
...123...
564...897
...231...
897...564
...564...

Выход

Valid

Ввод

123456789
987654321
123456789
123456789
987654321
123456789
123456789
987654321
123456789

Выход

Invalid

Правила для гольфа Code Code

Пожалуйста, разместите свой короткий код на любом языке, который решает эту проблему. Вход и вывод могут обрабатываться через stdin и stdout или другими файлами по вашему выбору.

Победитель будет самым коротким решением (по количеству байтов) на языке с реализацией, существующей до публикации этого вопроса. Поэтому, когда вы можете свободно использовать язык, который вы только что создали, чтобы отправить 0-байтовое решение, оно не будет учитываться, и вы, вероятно, получите downvotes.

4b9b3361

Ответ 1

Golfscript: 56

n%{zip''+9/.{'.'-..&=}%$0=\}:|2*{3/}%|;**"InvV"3/="alid"

Ответ 2

C: 165 162 161 160 159

int v[1566],x,y=9,c,b;main(){while(y--)for(x=9;x--+1;)if((c
=getchar()*27)>1242)b|=v[x+c]++|v[y+9+c]++|v[x-x%3+y/3+18+c]
++;puts(b?"Invalid":"Valid");return 0;}

Две новые строки не нужны. Один char, сохраненный josefx:-)...

Ответ 3

Haskell: 207 230 218 195 172

import List
t=take 3
h=[t,t.drop 3,drop 6]
v[]="V"
v _="Inv"
f s=v[1|v<-[s,transpose s,[g=<<f s|f<-h,g<-h]],g<-map(filter(/='.'))v,g/=nub g]++"alid\n"
main=interact$f.lines

Ответ 4

Perl: 168 128

$_=join'',<>;@a=/.../g;print+(/(\d)([^\n]{0,8}|(.{10})*.{9})\1/s
+map"@a[$_,$_+3,$_+6]"=~/(\d).*\1/,0..2,9..11,18..20)?Inv:V,alid

Первое регулярное выражение проверяет дубликаты, которые находятся в одной строке и столбце; второе регулярное выражение обрабатывает дубликаты в "том же поле".

Дальнейшее улучшение возможно, заменив \n в первом регулярном выражении литеральной новой строкой (1 char) или s >= Perl 5.12, заменив [^\n] на \n (3 char)

Ранее решение 168 char: Вход от stdin, выход - в stderr, потому что он делает все так просто. Linebreaks являются необязательными и не учитываются.

$_=join'',<>;$m=alid.$/;$n=Inv.$m;/(\d)(\N{0,8}|(.{10})*.{9})\1/s&&
die$n;@a=/.../g;for$i(0,8,17){for$j($i..$i+2){
$_=$a[$j].$a[$j+3].$a[$j+6];/(\d).*\1/&&die$n}}die"V$m"

Ответ 5

Python: 230 221 200 185

Сначала читаемая версия при len = 199:

import sys
r=range(9)
g=[raw_input()for _ in r]
s=[[]for _ in r*3]
for i in r:
 for j in r:
  n=g[i][j]
  for x in i,9+j,18+i/3*3+j/3:
<T>if n in s[x]:sys.exit('Invalid')
<T>if n>'.':s[x]+=n
print'Valid'

Так как SO не отображает символы табуляции, я использовал <T> для представления одного символа табуляции.

PS. тот же подход minEvilized до 185 символов:

r=range(9)
g=[raw_input()for _ in r]
s=['']*27
for i in r:
 for j in r:
    for x in i,9+j,18+i/3*3+j/3:n=g[i][j];s[x]+=n[:n>'.']
print['V','Inv'][any(len(e)>len(set(e))for e in s)]+'alid'

Ответ 6

Perl, 153 char

@B содержит 81 элемент платы.

&E проверяет, содержит ли подмножество @B любые повторяющиеся цифры

основной цикл проверяет каждый столбец, "блок" и строку головоломки

sub E{$V+="@B[@_]"=~/(\d).*\1/}
@B=map/\S/g,<>;
for$d(@b=0..80){
E grep$d==$_%9,@b;
E grep$d==int(($_%9)/3)+3*int$_/27,@b;
E$d*9..$d*9+8}
print$V?Inv:V,alid,$/

Ответ 7

Python: 159 158

v=[0]*244
for y in range(9):
 for x,c in enumerate(raw_input()):
  if c>".":
<T>for k in x,y+9,x-x%3+y//3+18:v[k*9+int(c)]+=1
print["Inv","V"][max(v)<2]+"alid"

< Т > является одним символом табуляции

Ответ 8

Общий Lisp: 266 252

(princ(let((v(make-hash-table))(r "Valid"))(dotimes(y 9)(dotimes(x
10)(let((c(read-char)))(when(>(char-code c)46)(dolist(k(list x(+ 9
y)(+ 18(floor(/ y 3))(- x(mod x 3)))))(when(>(incf(gethash(+(* k
9)(char-code c)-49)v 0))1)(setf r "Invalid")))))))r))

Ответ 9

Perl: 186

Вход от stdin, вывод в stdout, линейные входы необязательны.

@y=map/\S/g,<>;
sub c{(join'',map$y[$_],@$h)=~/(\d).*\1/|c(@_)if$h=pop}
print(('V','Inv')[c map{$x=$_;[$_*9..$_*9+8],[grep$_%9==$x,0..80],[map$_+3*$b[$x],@b=grep$_%9<3,0..20]}0..8],'alid')

(Linebreaks добавлены для "ясности".)

c() - это функция, которая проверяет ввод в @y на список списков номеров позиций, переданных в качестве аргумента. Он возвращает 0, если все списки позиций действительны (не содержат номера более одного раза) и 1 в противном случае, используя рекурсию для проверки каждого списка. Нижняя строка строит этот список списков, передает его на c() и использует результат для выбора правильного префикса для вывода.

Мне очень нравится то, что это решение использует "самоподобие" в списке позиций "block" в @b (которое избыточно перестраивается много раз, чтобы избежать @b=... в отдельном заявлении): верхнее левое положение i-го блока в пределах всей головоломки можно найти, умножив i-й элемент в @b на 3.

Больше распространения:

# Grab input into an array of individual characters, discarding whitespace
@y = map /\S/g, <>;

# Takes a list of position lists.
# Returns 0 if all position lists are valid, 1 otherwise.
sub c {
    # Pop the last list into $h, extract the characters at these positions with
    # map, and check the result for multiple occurences of
    # any digit using a regex.  Note | behaves like || here but is shorter ;)
    # If the match fails, try again with the remaining list of position lists.
    # Because Perl returns the last expression evaluated, if we are at the
    # end of the list, the pop will return undef, and this will be passed back
    # which is what we want as it evaluates to false.
    (join '', map $y[$_], @$h) =~ /(\d).*\1/ | c(@_) if $h = pop
}

# Make a list of position lists with map and pass it to c().
print(('V','Inv')[c map {
        $x=$_;                  # Save the outer "loop" variable
        [$_*9..$_*9+8],         # Columns
        [grep$_%9==$x,0..80],   # Rows
        [map$_+3*$b[$x],@b=grep$_%9<3,0..20]   # Blocks
    } 0..8],                    # Generates 1 column, row and block each time
'alid')

Ответ 10

Perl: 202

Я читаю Modern Perl и чувствую, что что-то кодирую... (довольно классная книга кстати:)

while(<>){$i++;$j=0;for$s(split//){$j++;$l{$i}{$s}++;$c{$j}{$s}++;
$q{(int(($i+2)/3)-1)*3+int(($j+2)/3)}{$s}++}}
$e=V;for$i(1..9){for(1..9){$e=Inv if$l{$i}{$_}>1or$c{$i}{$_}>1or$q{$i}{$_}>1}}
print $e.alid

Граф исключает ненужные строки перевода строки. Для этого может потребоваться Perl 5.12.2.

Немного читаем:

#use feature qw(say);
#use JSON;

#$json = JSON->new->allow_nonref;

while(<>)
{
    $i++;
    $j=0;
    for $s (split //)
    {
        $j++;
        $l{$i}{$s}++;
        $c{$j}{$s}++;
        $q{(int(($i+2)/3)-1)*3+int(($j+2)/3)}{$s}++;
    }
}

#say "lines: ", $json->pretty->encode( \%l );
#say "columns: ", $json->pretty->encode( \%c );
#say "squares: ", $json->pretty->encode( \%q );

$e = V;
for $i (1..9)
{
    for (1..9)
    {
        #say "checking {$i}{$_}: " . $l{$i}{$_} . " / " . $c{$i}{$_} . " / " . $q{$i}{$_};
        $e = Inv if $l{$i}{$_} > 1 or $c{$i}{$_} > 1 or $q{$i}{$_} > 1;
    }
}

print $e.alid;

Ответ 11

Ruby - 176

f=->x{x.any?{|i|(i-[?.]).uniq!}}
a=[*$<].map{|i|i.scan /./}
puts f[a]||f[a.transpose]||f[a.each_slice(3).flat_map{|b|b.transpose.each_slice(3).map &:flatten}]?'Invalid':'Valid'

Ответ 12

Lua, 341 байт

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

i=io.read("*a"):gsub("\n","")   -- Get input, and strip newlines
a={{},{},{}} -- checking array, 1=row, 2=columns, 3=squares
for k=1,3 do for l=1,9 do a[k][l]={0,0,0,0,0,0,0,0,0}end end -- fillup array with 0 (just to have non-nils)

for k=1,81 do -- loop over all numbers
    n=tonumber(i:sub(k,k):match'%d') -- get current character, check if it a digit, and convert to a number
    if n then
        r={math.floor((k-1)/9)+1,(k-1)%9+1} -- Get row and column number
        r[3]=math.floor((r[1]-1)/3)+3*math.floor((r[2]-1)/3)+1 -- Get square number
        for l=1,3 do v=a[l][r[l]] -- 1 = row, 2 = column, 3 = square
            if v[n] then -- not yet eliminated in this row/column/square
                v[n]=nil    
            else
                print("Double "..n.." in "..({"row","column","square"}) [l].." "..r[l]) --error reporting, just for the extra credit :)
                q=1 -- Flag indicating invalidity
            end
        end
    end
end
io.write(q and"In"or"","Valid\n")

версия для гольфа, 341 байт

f=math.floor p=io.write i=io.read("*a"):gsub("\n","")a={{},{},{}}for k=1,3 do for l=1,9 do a[k][l]={0,0,0,0,0,0,0,0,0}end end for k=1,81 do n=tonumber(i:sub(k,k):match'%d')if n then r={f((k-1)/9)+1,(k-1)%9+1}r[3]=f((r[1]-1)/3)+1+3*f((r[2]-1)/3)for l=1,3 do v=a[l][r[l]]if v[n]then v[n]=nil else q=1 end end end end p(q and"In"or"","Valid\n")

Ответ 13

Python: 140

v=[(k,c) for y in range(9) for x,c in enumerate(raw_input()) for k in x,y+9,(x/3,y/3) if c>'.']
print["V","Inv"][len(v)>len(set(v))]+"alid"

Ответ 14

ASL: 108

args1["\n"x2I3*x;{;{:=T(T'{:i~{^0}?})}}
{;{;{{,0:e}:;{0:^},u eq}}/`/=}:-C
dc [email protected];{:|}C&{"Valid"}{"Invalid"}?P

ASL - это язык сценариев, вдохновленный Golfscript, который я сделал.