tecnicas para operaciones matematicas matematica con como codigo avanzado algoritmo 9x9 3x3 algorithm code-golf sudoku

algorithm - para - sudoku con operaciones matematicas



Código de golf: Validar la cuadrícula de Sudoku (14)

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

Las dos nuevas líneas no son necesarias. Un personaje salvado por josefx :-) ...

Introducción

Una cuadrícula de Sudoku válida se llena con los números del 1 al 9, y ningún número aparece más de una vez en cada subbloque de 9, fila o columna. Lea este artículo para obtener más detalles si no está familiarizado con este rompecabezas popular.

Reto

El desafío es escribir el programa más corto que valida una cuadrícula de Sudoku que podría no estar completa.

La entrada será una cadena de 9 líneas de 9 caracteres cada una, que representa la cuadrícula. Una celda vacía estará representada por a . . Su salida debe ser Valid si la cuadrícula es válida; de lo contrario, no será válida.

Ejemplo

Entrada

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

Salida

Valid

Entrada

123456789 987654321 123456789 123456789 987654321 123456789 123456789 987654321 123456789

Salida

Invalid

Código de Reglas de Golf

Por favor, publique su código más corto en cualquier idioma que resuelva este problema. La entrada y la salida pueden manejarse mediante stdin y stdout o por otros archivos de su elección.

El ganador será la solución más corta (por byte count) en un lenguaje con una implementación existente antes de la publicación de esta pregunta. Entonces, si bien es libre de usar un lenguaje que acaba de crear para enviar una solución de 0 bytes, no contará, y probablemente obtendrá votos negativos.


Lisp Común: 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))


ASL: 108

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

ASL es un lenguaje de script inspirado en Golfscript que hice.


Golfscript: 56

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


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


Perl, 153 caracteres

@B contiene los 81 elementos del tablero.

&E comprueba si un subconjunto de @B contiene dígitos duplicados

bucle principal valida cada columna, "bloque" y fila del rompecabezas

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


Perl: 186

La entrada es desde stdin, salida a stdout, saltos de línea en la entrada opcional.

@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 añadido para "claridad".)

c() es una función que verifica la entrada en @y contra una lista de listas de números de posición pasados ​​como un argumento. Devuelve 0 si todas las listas de posiciones son válidas (no contienen ningún número más de una vez) y 1 de lo contrario, usando la recursión para verificar cada lista. La línea inferior construye esta lista de listas, la pasa a c() y usa el resultado para seleccionar el prefijo correcto para la salida.

Una cosa que me gusta es que esta solución aprovecha la "auto-similitud" en la lista de posiciones de "bloque" en @b (que se reconstruye redundantemente muchas veces para evitar tener @b=... en otra declaración): la posición superior izquierda del bloque i dentro de todo el rompecabezas se puede encontrar multiplicando el elemento i en @b por 3.

Más extendido:

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


Perl: 202

Estoy leyendo Modern Perl y tengo ganas de programar algo ... (por cierto, es un libro muy bueno :)

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

El conteo está excluyendo nuevas líneas innecesarias. Esto puede requerir Perl 5.12.2.

Un poco más legible:

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


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

El primer regex busca duplicados que estén en la misma fila y columna; el segundo regex maneja duplicados en el "mismo cuadro".

Es posible una mejora adicional al reemplazar /n en la primera expresión regular con una nueva línea literal (1 char), o con> = Perl 5.12, reemplazando [^/n] con /N (3 char)

Anteriormente, solución de 168 caracteres: la entrada es desde stdin, la salida es hacia stderr porque hace las cosas muy fáciles. Los saltos de línea son opcionales y no cuentan.

$_=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"


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"


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"

<T> es un carácter de pestaña única


Python: 230 221 200 185

Primero la versión legible en 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''

Como SO no muestra los caracteres de tabulación, he usado <T> para representar un solo carácter de tabulación.

PD. El mismo enfoque minimizó hasta 185 caracteres:

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


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


Lua, 341 bytes

Aunque sé que Lua no es el mejor idioma para jugar al golf, sin embargo, considerando su tamaño, creo que vale la pena publicarlo;). Versión sin golf, comentada e imprimiendo errores, para mayor diversión :)

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''s (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''s 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")

Versión golfeada, 341 bytes.

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