Перевірте головоломку королеви


16

Якщо ви не знаєте, що таке королева в шахах, це не має великого значення; це просто ім'я :)

Вашим входом буде квадрат довільної ширини та висоти, що містить деяку кількість маток. Вхідна плата буде виглядати приблизно так (ця плата має ширину та висоту 8):

...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q..

На цій дошці є 8 королеви. Якби тут було, скажімо, 7, 1 або 10, дошка не була б дійсною.

Тут ми використовуємо .для порожнього простору та Qдля королеви. Ви можете замість цього використовувати будь-який символ, який не потрібно пробілити.

Цей вхід може бути підтверджений як дійсний, і ви повинні надрукувати (або повернути) трибожне значення (якщо воно не було дійсним, слід надрукувати (або повернути) хибне значення). Це дійсно, оскільки жодна королева не знаходиться в тому ж рядку, стовпці, діагоналі чи антидіагоналі як інша .

Приклади (не виводити речі в дужки):

...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q..

1

...Q.
Q....
.Q...
....Q
..Q..

0

Q.
Q.

0

..Q
...
.Q.

0 (this is 0 because there are only 2 queens on a 3x3 board)


..Q.
Q...
...Q
.Q..

1

Q

1 (this is valid, because the board is only 1x1, so there's no queen that can take another)

Дозвольте наголосити, що введення є дійсним лише, якщо жодна королева не знаходиться в тому ж рядку, стовпці, діагоналі або антидіагоналі, як інший .

Правила

  • Ви ніколи не отримаєте порожній вхід
  • Якщо вхід містить менше цариць, ніж корінь sqaure області дошки, він недійсний.
  • Примітка немає дійсних рішень для 2x2 або 3x3 борту, але є рішення для будь-якого іншого розміру квадрата дошки, де ширина і висота - це натуральне число.
  • Вхід може бути у будь-якому розумному форматі, згідно з правилами PPCG
  • Вхід завжди буде площею
  • Я використовував 1 і 0 у прикладах, але ви можете використовувати будь-які триєдні або хибні значення (наприклад, Why yes, sir, that is indeed the caseта Why no, sir, that is not the case)

Оскільки це , виграє найкоротший код!



1
Would {(x, y, v)}з vв [., Q]бути допустимий формат вхідного сигналу?
PidgeyUsedGust

@DuctrTape Я не думаю, що це має багато сенсу.
Okx

2
@Okx Іншими словами, вони запитують про отримання списку координат і значень як вхідних даних. Наприклад: це (0, 0, Q), (0, 1, .), (1, 0, Q), (1, 1, .)був би третій тестовий випадок.
Мего

Чи можу я взяти рядок без розривів рядків?
Тит

Відповіді:


7

Равлики , 14 байт

&
o.,\Q!(z.,\Q

Спробуйте в Інтернеті!

Нічого подібного до двовимірної схеми відповідності мови для проблеми 2D-рішення. :)

Пояснення

&На першій лінії є варіантом режиму матч , який вимагає візерунка на другій лінії , щоб відповідати з будь-якої можливої позиції на вході. Якщо це так, програма друкує 1, інакше вона друкує 0.

Що стосується самого шаблону, зауважте, що )в кінці є неявна .

o       ,, Move in any orthogonal direction (up, down, left or right).
.,\Q    ,, Make sure that there's a Q somewhere in that direction from the
        ,, starting position of the match.
!(      ,, After finding the Q, make sure that the following part _doesn't_ match:
  z     ,,   Move in any orthogonal or diagonal direction.
  .,\Q  ,,   Try to find another Q in a straight line.
)

Чому це працює, найпростіше зрозуміти, починаючи з негативного пошуку: гарантуючи, що немає Qпрямої лінії від іншої, яку Qми вже знайшли, ми переконуємося, що не більше N королеви (інакше було б щоб вони були двома в одному ряду, і неможливо було б знайти цих цариць, не знайшовши іншого). Тоді перша частина, переконуючись, що є королева, досяжна в ортогональному напрямку з будь-якої позиції, переконайтеся, що є саме N королеви. Якби одного не було, був би рядок і стовпець без королеви. Починаючи з перетину цих, не вдасться знайти королеву, йдучи лише в ортогональному напрямку.


6

Желе , 17 або 15 байт

ỴµUŒD;ŒD;ZVṀ;V=1Ṃ

Спробуйте в Інтернеті!

Використовується для королеви та ¹для порожнього простору. (Це, головним чином, наслідок заборони приймати вхід як масив, тому що він змушує вхід бути рядками; перетворення рядків у цілі числа складно в Jelly. Найпростішим методом є оцінка, і виявляється, що замість 1 і 0, використовуючи "add 1" ( ) та "add 0" ( ¹) дозволяють опустити декілька інструкцій щодо суми та карти, тому що ми можемо порахувати королеви у списку, оцінивши її.) Значення truthy та falsey є нормальними для Jelly 1та 0.

EDIT: Питання було змінено з моменту написання цієї відповіді, щоб дозволити приймати дані як матрицю. Це дозволяє скинути провідні Ỵµ, заощаджуючи 2 байти. Це також, ймовірно, дозволяє змінити формат введення на щось більш нормальне, використовуючи Sпідсумовування, а не Vоцінювання, але я не думаю, що це економить байти, і мені подібний цей формат.

Пояснення

ỴµUŒD;ŒD;ZVṀ;V=1Ṃ
Ỵ                    Split on newlines.
 µ                   Set this value as the default for missing arguments.
     ;  ;            Concatenate the following three values:
  UŒD                - the antidiagonals;
      ŒD             - the diagonals;
         Z           - and the columns.
          V          Evaluate (i.e. count the queens on) all of those.
           Ṁ         Take the largest value among the results.
            ;V       Append the evaluation (i.e. queen count) of {each row}.
              =1     Compare each value to 1.
                Ṃ    Take the minimum (i.e. most falsey) result.

Отже, основна ідея полягає в тому, що ми гарантуємо, що на кожному антидіагоналі, діагоналі та стовпчику є щонайменше одна королева; і рівно по одній королеві на кожному ряду. Цих умов разом достатньо, щоб вимагати, щоб на кожному з чотирьох сортів лінії було щонайменше одна королева, а кількість королеви дорівнює довжині борту дошки.

Між іншим, Jelly, ймовірно, міг би вбудувати вбудований для антидіагоналів, але AFAICT, схоже, його не має, тому мені потрібно погодитися з відображенням дошки, а потім взяттям діагоналей.

Ще одна цікава примітка полягає в тому, що зміна =1Ṃна E(всі рівні) дає узагальнену перевірку n -quens, яка також прийме дошку n × n, де кожен рядок, стовпець, діагональ і антидіагонал містить не більше k королеви, а рада містить точно кн королеви. Обмеження k рівним 1 фактично коштувало двох байтів.


Правила були оновлені, тепер "Введення може бути у будь-якому розумному форматі, згідно з правилами PPCG", що повинно скоротити :) РЕДАКТУВАТИ - Я бачу, ви це помітили.
Джонатан Аллан

5

Октава, 57 70 67 51 52 байт

Збережено 1 байт, використовуючи flipзамість rot90@LuisMendo, але виявив помилку на корпусі 1x1

@(A)all(sum([A A' (d=@spdiags)(A) d(flip(A))],1)==1)

Вводить дані як двійкову матрицю, 1, яка представляє королеву, а 0 - порожній пробіл.

Створює анонімну функцію, яка спочатку об'єднує вхідну матрицю та її транспонирование.

spdiagsстворює матрицю з такою ж кількістю рядків, що і аргумент, при цьому діагоналі перетворюються на стовпчики (нульові, якщо це необхідно), тому з'єднують spdiagsвхідну матрицю, щоб отримати діагоналі та spdiagsматрицю, перевернуту горизонтально, щоб отримати антидіагоналі.

Тепер візьміть суму кожного стовпчика об'єднаної матриці і переконайтесь, що кожен стовпець рівно 1.

Зразок запущений на ideone .


Я думаю, ви можете використовувати flipзамістьrot90
Луїс Мендо

@LuisMendo Так, це теж буде працювати. Спасибі!
стакан

Крім того, ви не можете уникнути all()?
Луїс Мендо

@LuisMendo Ugh ... певно ... але доведеться почекати до обіду;)
стакан

4

MATL , 38 34 байт

4 байти від @beaker !

sG!sGt&n_w&:&XdsGP5M&Xdsv2<GnGzU=*

Вхід - це 2D масив нулів і одиниць, використовуючи крапки з комою як роздільники рядків.

Це виводить вектор стовпців, таких як truthy, і вектор стовпця, що містить принаймні один нуль, як помилковий.

Спробуйте в Інтернеті! Код нижнього колонтитулу - це ifгалузь, яка демонструє правдивість або хибність.

Або перевірити всі тестові випадки .

Пояснення

s      % Input binary matrix implicitly. Sum of columns. Gives a row vector
G!     % Paste input again. Transpose
s      % Sum of columns (rows in the original matrix). Gives a row vector
G      % Paste input again
t&n    % Duplicate. Push number of rows and number of columns (will be equal)
_w     % Negate, flip
&:     % Binary range. Gives [-n -n+1 ... n] for input of size n×n
&Xd    % Get diagonals -n through n. This gives all diagonals as colums
s      % Sum of each column (diagonals of original matrix). Gives a row vector
GP     % Paste input again. Flip vertically
5M     % Push [-n -n+1 ... n] again
&Xd    % Get diagonals -n through n (anti-diagonals of original matrix)
s      % Sum of each column. Gives a row vector
v      % Concatenate everything into a column vector
2<     % True for elements that are less than 2
Gn     % Paste input again. Number of elements
Gz     % Paste input again. Number of nonzeros (i.e. of queens)
U      % Square
=      % True if equal
*      % Mutiply, element-wise

Ви можете зберегти 2 байти, коли ви можете взяти двійкову матрицю як вхід.
стакан

2

J , 37 байт

(+/&,=#)*1=[:>./+//.,+//.&|.,+/,+/&|:

Послід анонімних функцій, який бере аргумент булевої матриці.

Спробуйте в Інтернеті!

( +/сума &з ,в Равель =дорівнює #бирки рядків)

* і (літ. разів)

1один =дорівнює [:на >./максимум

+/суми /.по діагоналі ,та (посилається на це)

+/суми по /.діагоналі &на |.зворотній стороні ,і

+/суми по ,і

+/суми &з |:транспонованою


2

SnakeEx , 67 байт

m:({q<>}({q<R>}[{q<RF>}{n<RF>}].)*{e<>}<R>)%{4}
e:.$
q:_*Q_*$
n:_+$

Використовується _замість .вводу. Повертає 1 або більше матчів за трили, 0 матчів за фальси. Ви можете знайти онлайн-перекладача за посиланням у заголовку.

Пояснення

SnakeEx - це мова із виклику 2-D Pattern Matching . Він визначає "змій", які рухаються по сітці, що відповідають предметам. Змії можуть нерестити інших змій, що робить мову досить потужною.

Давайте подивимось на цю програму знизу вгору.

n:_+$

Це визначає змію, nяка відповідає 1 або більше підкресленням, а потім краю сітки. Зверніть увагу, що це може бути в будь-якому з 8 кардинальних напрямків - напрямок визначається, коли змія нерестовича.

q:_*Q_*$

Як і nвище, це визначає qяк змію, яка відповідає будь-якій кількості підкреслень, одиничній Q, будь-якій кількості підкреслень та краю сітки. Іншими словами, рядок / стовпчик / діагональ, у якому є лише одна королева.

e:.$

e - змія, яка відповідає одному символу та краю сітки.

m:({q<>}({q<R>}[{q<RF>}{n<RF>}].)*{e<>}<R>)%{4}

Основна змія m використовує ці будівельні блоки для перевірки всієї дошки. Концептуально він проходить навколо зовнішніх країв сітки, нерестуючи інших змій, щоб перевірити, чи всі стовпці та рядки мають рівно одну королеву, а всі діагоналі мають максимум одну королеву. Якщо будь-яка з нерестуючих змій не відповідає, цілий сірник виходить з ладу. Давайте розбимо його.

  • ( )%{4}виконує те, що знаходиться в круглих дужках 4 рази, один раз для кожної сторони. (Далі далі, корисно зобразити певну сторону - скажімо, верхній край сітки, починаючи з верхнього лівого кута та рухаючись праворуч.)
  • {q<>}породжує qзмію в тому ж напрямку, в якому рухається головна змія. Це підтверджує, що поточний край відповідає правилу "точно одна королева". Зауважте, що нереалізовані змії не переміщують основний покажчик відповідності змій, тому ми все ще на початку краю.
  • ( )* відповідає 0 або більше того, що знаходиться в дужках.
  • {q<R>}нереститься qзмія, повернута праворуч від напрямку основної змії. (Наприклад, якщо основна змія рухається праворуч по верхньому краю, ця змія рухається вниз.) Це перевіряє кожен стовпчик / рядок.
  • [ ] відповідає одному з варіантів всередині дужок:
    • {q<RF>}нерест qзмія повернута на 45 градусів праворуч (тобто прямо Rі Fпрямо) в бік основної змії. qЗмія відповідає , якщо діагональ містить рівно одну королеву.
    • {n<RF>}нерест nзамість цього. nЗмія збігається , якщо діагональ не містить маток.
  • . відповідає будь-якому символу, переміщуючи покажчик відповідності вперед.
  • Перевіривши якомога більше горизонталей та діагоналей, ми перевіряємо, що ми на краю, нерестуючи {e<>}.
  • Нарешті, <R>повертає головну змію праворуч, готова відповідати наступному краю.

Дивні речі

  • У програмі немає нічого, що б гарантувало, що відповідність починається із зовнішнього кута. Насправді, тестові приклади, що стосуються правди, дають декілька збігів, деякі з яких десь починаються зсередини. Незважаючи на це, жоден із фальсифікованих справ, які я намагався, не породив помилкових позитивних результатів.
  • Якщо я читаю правильно специфікацію мови , я повинен був би мати можливість використовувати X(гілка в усіх діагональних напрямках) замість RF. На жаль, інтернет-перекладач сказав, що це синтаксична помилка. Я також спробував *(відділення у всіх напрямках), але це повісило перекладача.
  • Теоретично щось подібне _*Q?_*$повинно працювати для узгодження "максимум однієї королеви" по діагоналях, але це також повісило перекладача. Я здогадуюсь, що можливість порожніх сірників викликає проблеми.

2

Рубін, 120 байт

Функція лямбда заснована на оригінальній специфікації, яка вимагала введення як рядок.

->s{t=k=0
a=[]
s.bytes{|i|i>65&&(a.map{|j|t&&=((k-j)**4).imag!=0};a<<k)
k=i<11?k.real+1:k+?i.to_c}
t&&~a.size**2>s.size}

перетворює питання Q у складні числа і віднімає їх одне від одного. Якщо різниця між координатами будь-яких двох маток горизонтальна, вертикальна або діагональна, підвищення її до 4-ї потужності дасть дійсне число і розташування недійсне.

Ungolfed в тестовій програмі

f=->s{                                 #Take input as string argument.
  t=k=0                                #k=coordinate of character. t=0 (truthy in ruby.)
  a=[]                                 #Empty array for storing coordinates.
  s.bytes{                             #Iterate through all characters as bytes.
    |i|i>65&&(                         #If alphabetical, compare the current value of k to the contents of a
      a.map{|j|t&&=((k-j)**4).imag!=0} #If k-j is horizontal, vertical or diagonal, (k-j)**4 will be real and t will be false
      a<<k)                            #Add the new value of k to the end of a.
    k=i<11?k.real+1:k+?i.to_c          #If not a newline, increment the imaginary part of k. If a newline, set imaginary to 0 and increment real
  }                                    #s.size should be a*a + a newlines. ~a.size = -1-a.size, so ~a.size**2 = (a.size+1)**2
t&&~a.size**2>s.size}                  #compare a.size with s.size and AND the result with t. Return value. 


p f["...Q....
......Q.
..Q.....
.......Q
.Q......
....Q...
Q.......
.....Q.."]

p f["...Q.
Q....
.Q...
....Q
..Q.."]

p f["Q.
Q."]

p f["..Q
...
.Q."]

p f["..Q.
Q...
...Q
.Q.."]

p f["Q"]

2

Python 3 , 232 200 155 байт

d=1
f=input()
Q=[]
for i in f:d=[0,d][i.count('Q')==1];Q+=[(len(Q),i.index('Q'))]
print[0,d][sum(k[1]==i[1]or sum(k)==sum(i)for k in Q for i in Q)==len(Q)]

Спробуйте в Інтернеті!

-32 байти завдяки @beaker помітив зміни вхідних специфікацій; Я змінив мову з Python 3 на 2, дозволяючи мені використовувати inputдля введення введення як масив рядків або масив символьних масивів.

-45 байт завдяки монахині @Leaky


Вимоги до введення були послаблені, якщо це допоможе вам.
стакан

@beaker Добре, дякую. Я замість цього прийму введення як масив рядків. Дякуємо, що вказали на це!
HyperNeutrino


1

JavaScript (ES6), 115 байт

a=>!a.some((b,i)=>b.some((q,j)=>q&&h[i]|v[j]|d[i+j]|e[i-j]|!(h[i]=v[j]=d[i+j]=e[i-j]=1))|!h[i],h=[],v=[],d=[],e=[])

Безголівки:

function queens(arr) {
    horiz = [];
    vert = [];
    diag = [];
    anti = [];
    for (i = 0; i < arr.length; i++) {
        for (j = 0; j < arr.length; j++) {
            if (arr[i][j]) { // if there is a queen...
                if (horiz[i]) return false; // not already on the same row
                if (vert[j]) return false; // or column
                if (diag[i + j]) return false; // or diagonal
                if (anti[i - j]) return false; // or antidiagonal
                horiz[i] = vert[j] = diag[i + j] = anti[i - j] = true; // mark it
            }
        }
        if (!horiz[i]) return false; // fail if no queen in this row
    }
    return true;
}

0

Рубін, 155 байт

->x{(y=x.map{|r|(i=r.index ?Q)==r.rindex(?Q)?i:p or-2}).zip(y.rotate).map.with_index{|n,i|n.max-n.min==1&&i<y.size-1?-2:n[0]}.inject(:+)*2==(s=x.size)*~-s}

Це жахливо читати, тому у мене нижче трохи менше гольф-версії

->x{
    (y=x.map{|r|(i=r.index ?Q)==r.rindex(?Q)?i:p or-2})
    .zip(y.rotate)
    .map.with_index{|n,i|n.max-n.min==1&&i<y.size-1?-2:n[0]}
    .inject(:+)*2==(s=x.size)*~-s
}

Це той самий код, але з новими рядками, щоб відокремити те, що відбувається.

Сам код - це анонімна лямбда-функція, яка займає масив рядків (x ) у форматі["..Q", "Q..", ".Q."] .

Перший рядок - це зіставлення кожної рядки з індексом символу Q у цьому рядку. Якщо символу Q немає, його замінюють на -2 1 . Цей новий масив індексів призначений змінній y.

Наступний рядок зіпсує цей масив індексів, зміщений на один (повернутий). Це призводить до масиву пар послідовних індексів.

Наступний рядок особливо складний. Він проходить через кожну з пар індексів і віднімає менший з більшого. Якщо це 1 (а ми не в останній парі 2 ), то є дві королеви, які знаходяться на одній діагоналі, і вставляється значення -2, інакше вставляється початковий індекс королеви в рядку .

Останній рядок підсумовує всі індекси для кожного і перевіряє, чи є це число трикутника для n-1, де n - ширина (або висота) квадрата.

1: -1 було б моїм переходом, але це 1 окрім 0, так що я б заплутався у перевірці діагоналей. Негативність важливо зробити остаточну суму неправильною. Я думав про велику кількість (з однозначними цифрами), як 9, але не можу бути впевнений, що це не призведе до неправильної перевірки.
2: Дошка не обертається, тоді як rotateфункція масиву ruby виконує функції, а якщо остання пара відрізняється однією, це не має значення - це не діагональ.


0

PHP, 137 143 байт

натхненний рішенням Ніла

for($n=1+strlen($s=$argv[1])**.5|0;($c=$s[$p])&&!(Q==$c&&$v[$x=$p%$n]++|$h[$x=$p/$n]++|$d[$y-$x]++|$a[$y+$x]++);$p++);echo$n-1==count($a)&&!$c;

приймає дані з аргументу першого командного рядка; бігати з -r. Потрібні перерви в одному байті.
Насправді ви можете використовувати будь-який символ, але не 0для розриву рядка.
друкує true ( 1) або false (порожній рядок).

зламатися

for($n=1+strlen($s=$argv[1])**.5|0; // copy input to $s, $n=size+1 (for the linebreak)
    ($c=$s[$p])&&!(                 // loop through characters
        Q==$c&&                         // if queen: test and increment lines
            $v[$x=$p%$n]++|$h[$x=$p/$n]++|$d[$y-$x]++|$a[$y+$x]++
    );                                  // break if a line had been marked before
    $p++);
echo$n-1==count($a)             // print result: true for $n-1(=size) marks
    &&!$c;                      // and loop has finished

0

Пітон 3 , 185 176 175 172 171 байт

lambda x,c=lambda x:x.count("Q")==1:all([*map(c,x+[[l[i]for l in x]for i in range(len(x[0]))])])*~any(map(lambda s:"Q%sQ"%(s*".")in"".join(x),[len(x[0]),len(x[0])-2]))==-1

Анонімна функція, що приймає список рядків як вхідний.

Python 2 , 175 байт

lambda x:all([a.count("Q")==1for a in x]+[[l[i]for l in x].count("Q")==1for i in range(len(x[0]))]+[all(map(lambda s:"Q%sQ"%(s*".")not in"".join(x),[len(x[0]),len(x[0])-2]))])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.