Создать решение судоку 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.