Создать решение судоку CHECKER


21

Создать решение судоку CHECKER

Здесь есть куча СОЛВЕРСОВ Судоку, но я хочу, чтобы вы создали решение CHECKER настолько маленьким, насколько это возможно для человека (код-гольф).

  • Допустимая запись может принимать массив 9x9 в качестве аргумента (передаваемый по ссылке, сериализованный в командной строке, или как вы хотите его принять) или принимать входной файл, состоящий из девяти строк из девяти чисел для окончательной сетки , Смотрите примеры ввода ниже.

  • Допустимый ввод должен быть цифрами от 10 до 1 (1-9)

  • Пропущенные, пустые, лишние, нечисловые позиции или позиции с номерами за пределами 1-9 должны быть отклонены как недопустимый ввод, возвращая ненулевой результат, печатая ошибку или оба.

  • Ваша программа должна проверить, появляется ли каждое число один раз для столбца, один раз для строки и один раз для подсетки 3x3. Если оно прошло, верните «0», а если нет, верните ненулевой результат.

  • Следует избегать использования внешних ресурсов (веб-сайтов и т. Д.).

  • Если ваше решение представляет собой отдельную программу, выход с состоянием выхода или печать «0» или ненулевое значение для «Pass» или «Fail», соответственно, это нормально.

Пусть победит самый маленький ответ!

Примеры ввода:

c массив:

int input[9][9]={{1,2,3,4,5,6,7,8,9},
                 {4,5,6,7,8,9,1,2,3},
                 {7,8,9,1,2,3,4,5,6},
                 {2,3,1,5,6,4,8,9,7},
                 {5,6,4,8,9,7,2,3,1},
                 {8,9,7,2,3,1,5,6,4},
                 {3,1,2,6,4,5,9,7,8},
                 {6,4,5,9,7,8,3,1,2},
                 {9,7,8,3,1,2,6,4,5}
                };

файл:

123456789
456789123
789123456
231564897
564897231
897231564
312645978
645978312
978312645

9 подрешеток:

+---+---+---+
|123|456|789|
|456|789|123|
|789|123|456|
+---+---+---+
|231|564|897|
|564|897|231|
|897|231|564|
+---+---+---+
|312|645|978|
|645|978|312|
|978|312|645|
+---+---+---+

Ответы:


5

GolfScript, 39 символов

.zip.{3/}%zip{~}%3/{[]*}%++{$10,1>=!},,

Он принимает массив массивов в качестве входных данных (см. Онлайн-пример ) и выводит их, 0если это допустимая сетка.

Краткое объяснение кода

.zip         # Copy the input array and transpose it
.{3/}%       # Split each line into 3 blocks
zip{~}%      # Transpose these blocks
3/{[]*}%     # Do the same for the lines themselves and join again
++           # Make one large list of 27 9-element arrays 
             # (9 for rows, 9 for columns, 9 for blocks)
{$10,1>=!},  # From those 27 select the ones which are not a permutation of [1 2 3 ... 9]
             #   $      -> sort
             #   10,1>  -> [1 2 3 ... 9]
             #   =!     -> not equal
,            # Count after filtering

Мне нравится, что ненулевой вывод вашего кода является более значимым, чем просто 1или-1
Дэвид Уилкинс

Мне очень понравился твой ответ, но в итоге я решил не использовать решение для сценария гольфа. Я очень надеюсь, что вы понимаете
Дэвид Уилкинс

2
@DavidWilkins На самом деле я не понимаю - вы установили правила (!) И нигде не заявили, что GolfScript не разрешен.
Говард

Ваша точка зрения полностью обоснована ... на самом деле мне нечего оправдывать, не выбирая ваш ответ. Хорошо сыграно
Дэвид Уилкинс

10

Питон, 103

Я ненавижу судоку.

b = [[1,2,3,4,5,6,7,8,9],
     [4,5,6,7,8,9,1,2,3],
     [7,8,9,1,2,3,4,5,6],
     [2,3,1,5,6,4,8,9,7],
     [5,6,4,8,9,7,2,3,1],
     [8,9,7,2,3,1,5,6,4],
     [3,1,2,6,4,5,9,7,8],
     [6,4,5,9,7,8,3,1,2],
     [9,7,8,3,1,2,6,4,5]]

e=enumerate;print 243-len(set((a,t)for(i,r)in e(b)for(j,t)in e(r)for a in e([i,j,i/3*3+j/3]*(0<t<10))))

Как это работает: каждая строка, столбец и блок должны иметь каждое число от 1 до 9. Таким образом, для каждого 0 <= i, j < 9ячейка i,jнаходится в блоке 3*floor(i/3) + floor(j/3). Таким образом, существует 243 требования для удовлетворения. Я делаю каждое требование кортежем, ((item index,item type number),symbol)где item indexчисло от 0 до 8 (включительно), item type number0,1 или 2 для обозначения строки, столбца или блока соответственно и symbolявляется записью b[i][j].

Изменить: я по ошибке не проверил правильные записи. Теперь я делаю.


Ваша программа должна выводить, 0если решение прошло, нетTrue
Дэвид Уилкинс

@DavidWilkins, что за странное требование. Исправлена.
Boothby

Вы, сэр, получите мой голос именно за то, как вы начали свой ответ: D
Teun Pronk

9

APL (46)

{∧/,↑∊∘Z¨(/∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9),(↓⍵),↓⍉⍵}

Это занимает матрицу 9 на 9. Пример 1 можно ввести в TryAPL следующим образом:

     sudoku ← ↑(1 2 3 4 5 6 7 8 9)(4 5 6 7 8 9 1 2 3)(7 8 9 1 2 3 4 5 6)(2 3 1 5 6 4 8 9 7)(5 6 4 8 9 7 2 3 1)(8 9 7 2 3 1 5 6 4)(3 1 2 6 4 5 9 7 8)(6 4 5 9 7 8 3 1 2)(9 7 8 3 1 2 6 4 5)
     {∧/,↑∊∘Z¨(/∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9),(↓⍵),↓⍉⍵} sudoku
1

Объяснение:

  • ↓⍉⍵: получить столбцы ,
  • ↓⍵: получить ряды ,
  • 3/3⌿3 3⍴Z←⍳9: создайте матрицу 3 на 3, содержащую числа 1для 9, затем сделайте трижды каждое число в обоих направлениях, задав матрицу 9 на 9 с числами 1для 9обозначения каждой группы,
  • Z∘.=: для каждого номера, 1чтобы 9сделать битовую маску для данной группы,
  • /∘(,⍵)¨: и маска с каждым, давая группы .
  • ∊∘Z¨: Для каждого суб-массива, содержит ли он число 1к 9,
  • ∧/,↑: взять логическое andиз всех этих чисел вместе.

+1 Здорово! Но группы 3х3 можно сыграть в гольф еще. Например, это ↓9 9⍴1 3 2⍉3 3 9⍴⍵эквивалентно, /∘(,⍵)¨↓Z∘.=,3/3⌿3 3⍴Z←⍳9но довольно короче. Я уверен, что есть даже более короткие формулы.
Tobia

Кроме того, вы можете объединить матрицы по 1-му измерению и выполнить одно разбиение в конце:↓(9 9⍴1 3 2⍉3 3 9⍴⍵)⍪⍵⍪⍉⍵
Tobia

Есть ошибка: этот код ∊∘Z¨проверяет, состоит ли каждый вложенный массив (строка, столбец или блок) только из чисел от 1 до 9. Он не проверяет, представлены ли все числа. Вам нужно сделать что-то вроде Z∘.∊проверки, что каждое число в Z содержится в каждом подмассиве.
Tobia

И это ∧/,↑можно сократить до ∧/∊. Я сделал, я сделал! ;-)
Tobia

Очень компактный, но вы упустили один критический момент, который я сразу вижу:If it passes, return "0" and if not, return a non-zero result.
Дэвид Уилкинс

5

Java / C # - 183/180 181/178 173/170 байт

boolean s(int[][]a){int x=0,y,j;int[]u=new int[27];for(;x<(y=9);x++)while(y>0){j=1<<a[x][--y];u[x]|=j;u[y+9]|=j;u[x/3+y/3*3+18]|=j;}for(x=0;x<27;)y+=u[x++];return y==27603;}

(Изменение booleanк boolдля C #)

отформатирован:

boolean s(int[][] a){
    int x=0, y, j;
    int[] u=new int[27];
    for(;x<(y=9);x++)
        while(y>0){
            j=1<<a[x][--y];
            u[x]|=j;
            u[y+9]|=j;
            u[x/3+y/3*3+18]|=j;
        }

    for(x=0;x<27;)
        y+=u[x++];

    return y==27603;
}

Метод создает массив uс 27 битовыми масками, представляющими цифры, найденные в девяти строках, столбцах и квадратах.

Затем он выполняет итерацию по всем ячейкам, выполняя операцию 1 << a[x][y]для создания битовой маски, представляющей цифру, и OR для ее столбца, строки и квадратной битовой маски вместе с ней.

Затем он перебирает все 27 битовых масок, гарантируя, что все они в сумме составят 27594 (1022 * 9, 1022 - битовая маска для всех имеющихся цифр 1-9). (Обратите внимание, что в yитоге получается 27603, поскольку он уже содержит 9 после двойной петли.)

Изменить: случайно оставил в, %3что больше не нужно.

Редактировать 2: Вдохновленный комментарием Брайса Вагнера, код был сжат еще немного.


Почти тот же алгоритм в C # 149 символов (но только если разрешен Linq): bool s (int [] a) {int x = 0, y, j; var u = new int [27]; while (x ++ <(y) = 9)) , а (у> 0) {= 1 << а [х + 9 * - у]; и [х] | = J; и [у + 9] | = J; и [х / 3 + y / 3 * 3 + 18] | = j;} return u.Sum () == 27594;}
Брайс Вагнер

@BryceWagner Linq действительно был бы полезен. Тем не менее, мое решение для Java с C # является запоздалой мыслью (даже не упомянутой в оригинальном посте) и, таким образом, с более низким приоритетом. Я также использовал одномерные массивы для компактности в начале, прежде чем принять решение против этого (в качестве примеров используются двумерные). Тем не менее, ваш код дал мне несколько идей о том, как можно сбрить еще несколько байтов. :)
Smallhacker

3

питон = 196

Не самый удачный, но идея есть. Наборы довольно полезны.

Совет:

b = [[1,2,3,4,5,6,7,8,9],
     [4,5,6,7,8,9,1,2,3],
     [7,8,9,1,2,3,4,5,6],
     [2,3,1,5,6,4,8,9,7],
     [5,6,4,8,9,7,2,3,1],
     [8,9,7,2,3,1,5,6,4],
     [3,1,2,6,4,5,9,7,8],
     [6,4,5,9,7,8,3,1,2],
     [9,7,8,3,1,2,6,4,5]]

Программа:

n={1,2,3,4,5,6,7,8,9};z=0
for r in b:
 if set(r)!=n:z=1
for i in zip(*b):
 if set(i)!=n:z=1
for i in (0,3,6):
 for j in (0,3,6):
  k=j+3
  if set(b[i][j:k]+b[i+1][j:k]+b[i+2][j:k])!=n:z=1
print(z)

s / {1,2,3,4,5,6,7,8,9} / set (range (1,10)) / сохраняет 3 символа.
MatrixFrog

В Python 3.5 вы можете использовать n={*range(1,10)}, но это новее, чем вызов. Вместо этого используйте set(range(1,10))как MatrixFrog сказал.
mbomb007

3

Java - 385 306 328 260 символов

Редактировать: я по глупости неверно истолковал инструкции, что ответом должна была быть полная программа. Так как это может быть только допустимая функция, я переписал и минимизировал ее до функции и переписал свое введение в решение с учетом этого.

Итак, как вызов самому себе, я подумал, что постараюсь сделать наименьшее средство проверки Java-решений.

Для достижения этого я предполагаю, что головоломка судоку будет передана в виде многомерного массива Java, например, так:

s(new int[][] {
    {1,2,3,4,5,6,7,8,9},
    {4,5,6,7,8,9,1,2,3},
    {7,8,9,1,2,3,4,5,6},
    {2,3,1,5,6,4,8,9,7},
    {5,6,4,8,9,7,2,3,1},
    {8,9,7,2,3,1,5,6,4},
    {3,1,2,6,4,5,9,7,8},
    {6,4,5,9,7,8,3,1,2},
    {9,7,8,3,1,2,6,4,5}});

Затем у нас есть реальный решатель, который возвращает «0», если верное решение, «1», если нет.

Полностью в гольф:

int s(int[][] s){int i=0,j,k=1;long[] f=new long[9];long r=0L,c=r,g=r,z=45L,q=r;for(f[0]=1L;k<9;){f[k]=f[k-1]*49;z+=f[k++]*45;}for(;i<9;i++){for(j=0;j<9;){k=s[i][j];r+=k*f[i];c+=k*f[j];g+=k*f[j++/3+3*(i/3)];q+=5*f[k-1];}}return (r==z&&c==z&&g==z&&q==z)?0:1;}

Удобочитаемый:

    int s(int[][] s) {
        int i=0,j,k=1;
        long[] f=new long[9]; 
        long r=0L,c=r,g=r,z=45L,q=r;
        for(f[0]=1L;k<9;){f[k]=f[k-1]*49;z+=f[k++]*45;}
        for(;i<9;i++) {
            for (j=0;j<9;) {
                k=s[i][j];
                r+=k*f[i];
                c+=k*f[j];
                g+=k*f[j++/3+3*(i/3)];
                q+=5*f[k-1];
            }
        }
        return (r==z&&c==z&&g==z&&q==z)?0:1;
    }

Так как же это работает? По сути, я просто создаю свою собственную числовую базу с достаточным разрешением в каждой цифре, поэтому мне нужно всего лишь сделать три числовых сравнения после прохождения головоломки, чтобы узнать, является ли она действительной. Я выбрал базу 49 для этой задачи, но любой базы больше 45 будет достаточно.

(Надеюсь) ясный пример: представьте, что каждая «строка» в загадке судоку представляет собой одну цифру в числе base-49. Мы представим каждую цифру в числе base-49 как число base-10 в векторе для простоты. Итак, если все строки «правильные», мы ожидаем следующее число base-49 (как вектор base-10):

(45,45,45,45,45,45,45,45,45)

или преобразовать в одно число-10: 1526637748041045

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

Правка для устранения уязвимости всех 5 и других связанных с этим проблем: я добавляю четвертое число базы 49, основываясь на идее, что в каждой головоломке должно быть по 9 каждого числа. Итак, я добавляю 5 к каждой цифре в числе base-49 для каждого вхождения числа base-10, которое представляет индекс цифры. Например, если есть 10 9 и 9 8, 9 7, 8 6 и 9 других, вы получите число base-49 (как вектор base-10 размера 10, чтобы справиться с переполнением):

(1, 1, 45, 45, 40, 45, 45, 45, 45, 45)

Который потерпит неудачу при сравнении с нашим «идеальным» числом base-49.

Мое решение использует преимущества этого математического решения, чтобы избежать как можно большего количества циклов и сравнения. Я просто использую longзначение для хранения каждого числа base-49 как числа base-10 и использую массив поиска, чтобы получить «факторы» для каждой цифры base-49 во время вычисления значения проверки столбца / строки / подсетки.

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

Дайте мне знать, что вы думаете.


1
На самом деле, это страдает от той же уязвимости, о которой упоминал @ steve-verrill - все 5 или любой набор чисел, сумма которых равна 45, «обманут» решатель. Я собираюсь пересмотреть. У меня есть идея, как победить это.
ProgrammerDan

Я исправил эту уязвимость в своем последнем обновлении. Теперь этот случай рассматривается и всеми остальными в своем роде. По сути, это был серьезный недосмотр, чтобы не иметь дело с «подсчетами» каждого типа цифр основания-10. Теперь я выполняю эту проверку напрямую, но с использованием того же математического подхода (номер базы 49).
ProgrammerDan

Дэн, спасибо за подтверждение. Я видел это и удивлялся, почему я не был уведомлен, но я вижу, что ты вставил черту в мое имя. Это, кажется, запутало систему. Просто пропустите пространство. Я рассмотрю вопрос об изменении способа отображения моего имени.
Уровень Река St

Ахха, это объясняет это. Спасибо @steveverrill - я все еще привыкаю к ​​стековому обмену. Тем не менее, ваше краткое использование принципа суммы 45 было блестяще заявлено. Сделано мое решение дольше, чтобы преодолеть его, но это жизнь!
ProgrammerDan



2

Perl, 193 байта

for(@x=1..9){$i=$_-1;@y=();push@y,$a[$i][$_-1]for@x;@y=sort@y;$r+=@y~~@x;@y=();push@y,$a[3*int($i/3)+$_/3][3*($i%3)+$_%3]for 0..8;@y=sort@y;$r+=@y~~@x}for(@a){@y=sort@$_;$r+=@y~~@x}exit($r!=27)

Ввод ожидается в виде массива:

@a=(
    [1,2,3,4,5,6,7,8,9],
    [4,5,6,7,8,9,1,2,3],
    [7,8,9,1,2,3,4,5,6],
    [2,3,1,5,6,4,8,9,7],
    [5,6,4,8,9,7,2,3,1],
    [8,9,7,2,3,1,5,6,4],
    [3,1,2,6,4,5,9,7,8],
    [6,4,5,9,7,8,3,1,2],
    [9,7,8,3,1,2,6,4,5]
);

Код выхода равен 0, если @aэто решение, в противном случае 1возвращается.

Безголовая версия:

@x = (1..9);
for (@x) {
    $i = $_ - 1;
    # columns
    @y = ();
    for (@x) {
        push @y, $a[$i][$_-1];
    }
    @y = sort @y;
    $r += @y ~~ @x;
    # sub arrays
    @y = ();
    for (0..8) {
        push @y, $a[ 3 * int($i / 3) + $_ / 3 ][ 3 * ($i % 3) + $_ % 3 ];
    }
    @y = sort @y;
    $r += @y ~~ @x
}
# rows
for (@a) {
    @y = sort @$_;
    $r += @y ~~ @x
}
exit ($r != 27);

Каждая из 9 строк, 9 столбцов и 9 вложенных массивов помещается в отсортированный массив и проверяется, соответствует ли он массиву (1..9). Число $rувеличивается для каждого успешного совпадения, которое должно составлять до 27 для правильного решения.


2

J 52 54

-.*/,(9=#)@~.@,"2(0 3 16 A.i.4)&|:(4#3)($,)".;._2]0 :0

Принимает аргумент, вставленный в командную строку и заканчивающийся символом а):

1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 1 5 6 4 8 9 7
5 6 4 8 9 7 2 3 1
8 9 7 2 3 1 5 6 4
3 1 2 6 4 5 9 7 8
6 4 5 9 7 8 3 1 2
9 7 8 3 1 2 6 4 5
)

Возвращает 1, если прошло, 0, если нет.

Внутри он преобразует сетку 9x9 в сетку 3x3x3x3 и выполняет некоторые перестановки на осях, чтобы получить искомую единицу (строки, линии и прямоугольники) в последних двух измерениях.

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

Возможно, далеко от совершенства, но уже превосходит большинство ;-)


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

0 за пас это идиотизм. Есть причина, по которой Boole выбрал 1 для true и 0 для false. Но ты прав. Добавляет 2 символа.
jpjacobs

Думайте об этом как о статусе выхода, а не как логическое значение
Дэвид Уилкинс

Я выбираю ваш ответ, потому что он работает. Вы следовали правилам, и ваша программа очень короткая. Благодарность!
Дэвид Уилкинс

Ну, я обманываю ... По правде говоря, я не могу оправдать не выбор ответа от Golfscript, который короче вашего ... Но слава за 2-е место
Дэвид Уилкинс

2

Mathematica, 84 79 символов

f=Tr[Norm[Sort@#-Range@9]&/@Join[#,Thread@#,Flatten/@Join@@#~Partition~{3,3}]]&

Примеры:

f[{{1,2,3,4,5,6,7,8,9},
   {4,5,6,7,8,9,1,2,3},
   {7,8,9,1,2,3,4,5,6},
   {2,3,1,5,6,4,8,9,7},
   {5,6,4,8,9,7,2,3,1},
   {8,9,7,2,3,1,5,6,4},
   {3,1,2,6,4,5,9,7,8},
   {6,4,5,9,7,8,3,1,2},
   {9,7,8,3,1,2,6,4,5}}]

0

f[{{2,1,3,4,5,6,7,8,9},
   {4,5,6,7,8,9,1,2,3},
   {7,8,9,1,2,3,4,5,6},
   {2,3,1,5,6,4,8,9,7},
   {5,6,4,8,9,7,2,3,1},
   {8,9,7,2,3,1,5,6,4},
   {3,1,2,6,4,5,9,7,8},
   {6,4,5,9,7,8,3,1,2},
   {9,7,8,3,1,2,6,4,5}}]

2

f[{{0,2,3,4,5,6,7,8,9},
   {4,5,6,7,8,9,1,2,3},
   {7,8,9,1,2,3,4,5,6},
   {2,3,1,5,6,4,8,9,7},
   {5,6,4,8,9,7,2,3,1},
   {8,9,7,2,3,1,5,6,4},
   {3,1,2,6,4,5,9,7,8},
   {6,4,5,9,7,8,3,1,2},
   {9,7,8,3,1,2,6,4,5}}]

3


Ваш третий пример вывода: 3всегда указывает на неверный ввод, или это иногда является ответом на неудачное решение?
Дэвид Уилкинс

2

Javascript ES6, 150 символов

Принимает ввод в виде строки из 81 символа без каких-либо разделителей.

s=>s.match("^(?=(#.{0,8}#.{9})+$)(?=(#(.{9}){0,8}#.){9})((#.?.?(.{9}){0,2}#...){3}.{18})+$".replace(/#(.*?)#/g,"123456789".replace(/./g,"(?=$$1$&)")))

Функция возвращает nullотрицательный ответ, а массив с исходной строкой в ​​первом элементе - как положительный. Можно изменить на bool, добавив !!в начало функции.

Тест (см. Связанные задачи для более подробно):

f=s=>s.match("^(?=(#.{0,8}#.{9})+$)(?=(#(.{9}){0,8}#.){9})((#.?.?(.{9}){0,2}#...){3}.{18})+$".replace(/#(.*?)#/g,"123456789".replace(/./g,"(?=$$1$&)")))
;`123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298`
.split`
`.every(f)
&&
`519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825`
.split`
`.every(s => !f(s))

Это одно смешное выражение ... Удивительная работа.
ETHproductions

2

R, 63 50 байт

Предполагается, что входные данные mпредставляют собой матрицу чисел 9x9.

all(apply(m,1,match,x=1:9),apply(m,2,match,x=1:9))

Я был прав, что дальнейшая игра в гольф была возможна.

Объяснение:

    apply(m,1,match,x=1:9),

Возьмите m, и для каждой строки примените matchфункцию. Мы указываем дополнительный аргумент x=1:9для передачи match. xявляется аргументом первой позиции по умолчанию, и поэтому каждая строка помещается во позицию второго аргумента, то есть table. Функция matchищет экземпляры xв table. В этом случае, он ищет 1:9(цифры от 1 до 9) в каждой строке. Для каждого из 1:9он вернется TRUE(или FALSE), если этот номер найден (или нет).

Таким образом, это приводит к серии из 81 логических значений.

                           apply(m,2,match,x=1:9)

Повторите вышеуказанное для каждого столбца ввода.

all(                                             )

Наконец, allпроверяет, является ли каждый элемент списка логических значений TRUE. Это будет иметь место в том и только в том случае, если решение является правильным (то есть каждое число 1:9присутствует только один раз в каждом столбце и каждой строке).

Старый подход:

for(i in 1:2)F=F+apply(m,i,function(x)sort(x)==1:9);sum(F)==162

Он берет каждый ряд, сортирует его, а затем сравнивает его с [1, 2, ... 9]. Правильный ряд должен точно соответствовать. Затем он делает то же самое для каждого столбца. Всего у нас должно быть 162 точных совпадения, что и проверяет последняя часть. Здесь, вероятно, есть некоторые возможности для дальнейшего игры в гольф ...


Похоже, вы проверяете столбцы и строки, но не ящики ...
JayCe

1

Haskell - 175

import Data.List
c=concat
m=map
q=[1..9]
w=length.c.m (\x->(x\\q)++(q\\x))
b x=c.m(take 3.drop(3*mod x 3)).take 3.drop(3*div x 3)
v i=sum$m(w)[i,transpose i,[b x i|x<-[0..8]]]

Эта функция vвызывается. Он работает, получая разность каждой строки, столбца и блока по списку [1..9]и суммируя длины этих списков различий.

Демо на примере Судоку:

*Main> :l so-22443.hs 
[1 of 1] Compiling Main             ( so-22443.hs, interpreted )
Ok, modules loaded: Main.
*Main> v [[1,2,3,4,5,6,7,8,9],[4,5,6,7,8,9,1,2,3],[7,8,9,1,2,3,4,5,6],[2,3,1,5,6,4,8,9,7],[5,6,4,8,9,7,2,3,1],[8,9,7,2,3,1,5,6,4],[3,1,2,6,4,5,9,7,8],[6,4,5,9,7,8,3,1,2],[9,7,8,3,1,2,6,4,5]]
0

1

Javascript - 149 символов

r=[];c=[];g=[];for(i=9;i;)r[o=--i]=c[i]=g[i]=36;for(x in a)for(y in z=a[x]){r[v=z[y]-1]-=y;c[v]-=x;g[v]-=3*(x/3|0)+y/3|0}for(i in r)o|=r[i]|c[i]|g[i]

Ожидает существование массива aи создает переменную oдля вывода, которая 0в случае успеха и не равна нулю в противном случае.

Работает, проверяя, что сумма позиции, в которой каждое значение встречается для каждой строки, столбца и сетки 3 * 3, равна 36 (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8).

тестирование

a=[
    [1,2,3, 4,5,6, 7,8,9],
    [4,5,6, 7,8,9, 1,2,3],
    [7,8,9, 1,2,3, 4,5,6],

    [2,3,1, 5,6,4, 8,9,7],
    [5,6,4, 8,9,7, 2,3,1],
    [8,9,7, 2,3,1, 5,6,4],

    [3,1,2, 6,4,5, 9,7,8],
    [6,4,5, 9,7,8, 3,1,2],
    [9,7,8, 3,1,2, 6,4,5]
  ];

Дает 'o = 0'

a=[
    [1,2,3, 4,5,6, 7,8,9],
    [4,5,6, 7,8,9, 1,2,3],
    [7,8,9, 1,2,3, 4,5,6],

    [2,3,1, 5,6,4, 8,9,7],
    [5,6,4, 8,9,7, 2,3,1],
    [8,9,7, 2,3,1, 5,6,4],

    [3,1,2, 6,4,5, 9,7,8],
    [6,4,5, 9,7,8, 3,1,2],
    [9,7,8, 3,1,2, 6,5,4]
  ];

(Последние 2 цифры поменялись местами)

дает o=-1

a=[
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],

    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],

    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5],
    [5,5,5, 5,5,5, 5,5,5]
  ];

дает o=-284


1

Haskell, 121 130 127 байтов (87 Lambdabot)

import Data.List
import Data.List.Split
c=concat
t=transpose
k=chunksOf
p x=all(==[1..9])$(sort<$>)=<<[x,t x,k 9.c.c.t$k 3<$>x]

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

-- k 9.c.c.t$k 3<$> x = chunksOf 9 $ concat $ concat $ transpose $ map chunksOf 3 x

let ts = k 9$[10*a+b|a<-[1..9],b<-[1..9]] --yep, this is ugly
in k 9.c.c.t$k 3<$>ts
-- prints:
--[[11,12,13,21,22,23,31,32,33],[41,42,43,51,52,53,61,62,63],[71,72,73,81,82,83,91,92,93],[14,15,16,24,25,26,34,35,36],[44,45,46,54,55,56,64,65,66],[74,75,76,84,85,86,94,95,96],[17,18,19,27,28,29,37,38,39],[47,48,49,57,58,59,67,68,69],[77,78,79,87,88,89,97,98,99]]

Lambdabot загружает Data.List и Data.List.Split по умолчанию (я не думаю, что решение BlackCap проверяет флажки).

Идеи по улучшению приветствуются

// Редактировать: я испортил :)
// Редактировать: 3 байта сохранены BlackCap


Вы правы, я не заметил, что проверки строк и столбцов недостаточно ...
BlackCap

хорошо, я также испортил :)
michi7x7

1
Вы можете заменить (map sort)на(sort<$>)
BlackCap

1
И .c$(sort<$>)<$>с$(sort<$>)=<<
BlackCap

о боже, я должен был вспомнить эти 2
michi7x7


0

Clojure, 151 байт

Довольно долго, но другие, похоже, тоже. Также раздражает, что объединение множеств требует a require, поэтому вместо этого я использовал конкатат векторов.

Итерирует по каждой строке и столбцу, и если значение находится в диапазоне от 1 до 9, оно испускает три вектора, один для строки, столбца и ячейки 3х3. Возвращает 0 в случае успеха, в nilпротивном случае два дополнительных символа могут вернуть 1 в случае неудачи. Возвращает числа за пределами 1 - 9, возвращая их, nilно приводит к сбою при других аномалиях, таких как нецелые значения. Коэффициенты 0 - 2, поэтому можно безопасно использовать значения 8и 9дифференцировать значения ячеек от строк и столбцов.

(fn[s](if(= 243(count(set(apply concat(for[i(range 9)j(range 9)](let[v(nth(nth s i)j)q #(quot % 3)](if(<= 1 v 9)[[8 v i][9 v j][(q i)(q j)v]])))))))0))

Вход - это вложенный вектор векторов (так что nthработает):

(def sudoku [[1 2 3 4 5 6 7 8 9]
             [4 5 6 7 8 9 1 2 3] 
             [7 8 9 1 2 3 4 5 6] 
             [2 3 1 5 6 4 8 9 7] 
             [5 6 4 8 9 7 2 3 1] 
             [8 9 7 2 3 1 5 6 4] 
             [3 1 2 6 4 5 9 7 8] 
             [6 4 5 9 7 8 3 1 2] 
             [9 7 8 3 1 2 6 4 5]])

Ungolfed:

(defn f [s]
  (->> (for [i (range 9) j (range 9)]
         (let [v (-> s (nth i) (nth j)) q #(quot % 3)]
           (if (<= 1 v 9)
             [[:row v i] [:col v j] [:cell [(q i) (q j)] v]])))
    (apply concat)
    set
    count
    (#(if (= 243 %) :pass :fail))))

0

PHP, 196 190 байт

while($i<9){for($b=$c=$k=$y="";$y++<9;)$b.=($a=$argv)[$y][$i];for(;$k<3;)$c.=substr($a[++$k+$i-$i%3],$i%3*3,3);if(($u=count_chars)($a[++$i],3)<($d=123456789)|$u($b,3)<$d|$u($c,3)<$d)die(1);}

Программа принимает 9 отдельных аргументов командной строки (по одной строке цифр для каждой строки сетки);
выходит с 1ошибкой (ошибка),0 (ок) для действительного.

Беги с php -nr '<code>' <row1> <row2> ....

сломать

while($i<9)
{
    for($b=$c=$k=$y="";$y++<9;)$b.=($a=$argv)[$y][$i];  // column to string
    for(;$k++<3;)$c.=substr($a[$i-$i%3+$k],$i%3*3,3);   // sub-grid to string
    if(($u=count_chars)($a[++$i],3)<($d=123456789)      // check row
        |$u($b,3)<$d                                    // check column
        |$u($c,3)<$d                                    // check sub-grid
    )die(1);                                            // test failed: exit with 1
}

объяснение

count_charsсчитает символы в строке и обычно создает массив с кодами ascii в качестве ключей и количеством символов в качестве значений; но с 3параметром mode он создает отсортированную строку из символов; и это можно легко сравнить с числом с нужными цифрами.

Сравнение не только проверяет дубликаты, но также включает проверку на недопустимые символы. И это только требует <, а не !=потому, что это числовое сравнение: PHP будет интерпретировать строку как число, насколько это возможно. 123e56789, 0x3456789Или подобное не может появиться, потому что символы сортируются; и любое чистое целое число с отсутствующей цифрой меньше чем 123456789... и .23456789тоже, конечно.

$a=$argvсохраняет один байт, $d=123456789сохраняет девять и $u=count_charsсохраняет 13.


-1

C # - 306 298 288 символов

Следующая консольная программа использовалась для вызова функции проверки;

static void Main(string[] args)
    {
        int[,] i={{1,2,3,4,5,6,7,8,9},
             {4,5,6,7,8,9,1,2,3},
             {7,8,9,1,2,3,4,5,6},
             {2,3,1,5,6,4,8,9,7},
             {5,6,4,8,9,7,2,3,1},
             {8,9,7,2,3,1,5,6,4},
             {3,1,2,6,4,5,9,7,8},
             {6,4,5,9,7,8,3,1,2},
             {9,7,8,3,1,2,6,4,5}
            };

            Console.Write(P(i).ToString());
    }

Все, что это делает, это инициализирует массив и передает его в функцию проверки P.

Функция проверки указана ниже (в форме для игры в гольф);

private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];for(int p=0;p<9;p++){r[p]=45;c[p]=45;g[p]=45;}for(int y=0;y<9;y++){for(int x=0;x<9;x++){r[y]-=i[x,y];c[x]-=i[x,y];int k=(x/3)+((y/3)*3);g[k]-=i[x,y];}}for(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}

Или в полностью разложенном виде;

    private static int P(int[,] i)
    {
        int[] r = new int[9],c = new int[9],g = new int[9];
        for (int p = 0; p < 9; p++)
        {
            r[p] = 45;
            c[p] = 45;
            g[p] = 45;
        }

        for (int y = 0; y < 9; y++)
        {
            for (int x = 0; x < 9; x++)
            {
                r[y] -= i[x, y];

                c[x] -= i[x, y];

                int k = (x / 3) + ((y / 3) * 3);
                g[k] -= i[x, y];
            }
        }

        for (int p = 0; p < 9; p++)
            if (r[p] > 0 | c[p] > 0 | g[p] > 0) return 1;

        return 0;
    }

При этом используется идея, что все столбцы, строки и подрешетки должны составлять до 45. Он работает через входной массив и вычитает значение каждой позиции из его строки, столбца и подсетки. После завершения он проверяет, что ни одна из строк, столбцов или подрешеток не имеет значения.

По запросу возвращает 0, если массив является допустимым решением Судоку, и ненулевое (1), где это не так.


Я думаю, что вы можете сохранить некоторые символы, используя private static int P(int[,]i){int[]r=new int[9],c=new int[9],g=new int[9];вместо этого. (Обратите внимание на удаление пробела после закрывающей квадратной скобки ].) Кроме того, я не уверен, но я думаю, что вы можете избавиться от private static.
user12205

Также, в последней части, в C мы можем удалить некоторые фигурные скобки, т.е. for(int p=0;p<9;p++)if(r[p]>0|c[p]>0|g[p]>0)return 1;return 0;}не уверены, работает ли он в C #. (Я на самом деле не знаю C #)
user12205

@ace - я сделал несколько улучшений на основе ваших предложений. Теперь до 298 символов.
Уилл

Подрезал еще 10 символов на основе комментариев @ace.
Будет ли

1
Что происходит с массивом, полным чисел 5? Все строки, столбцы и квадраты в сумме составляют 45.
Уровень River St
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.