Розв’яжіть хроматичну загадку


35

У наших друзів на Puzzling.SE була розміщена така загадка: Чи завжди ця хроматична головоломка вирішується? автор Едгар Г. Ви можете зіграти тут .

Пояснення головоломки

Давши m x nсітку з плитками трьох різних кольорів, ви можете вибрати будь-яку дві сусідні плитки , якщо їх кольори різні . Ці дві плитки потім перетворюються в третій колір, тобто в один колір, який не представлений цими двома плитками. Головоломка вирішується, якщо всі плитки мають однаковий колір . Мабуть, можна довести, що ця головоломка завжди вирішується, якщо ні те, mні nділяться на 3.

8х8 триколірна головоломка

Звичайно, це вимагає алгоритму вирішення. Ви напишете функцію або програму, яка вирішує цю загадку. Зауважте, що функції з "побічними ефектами" (тобто вихідний показник увімкнено, stdoutа не в якомусь незручному поверненому типі даних) явно дозволені.

Введення-виведення

Вхід буде m x nматриця , що складається з цілих чисел 1, 2і 3(або 0, 1, 2якщо це зручно). Ви можете взяти цей ввід у будь-якому розумному форматі. І те, mі nє, >1і не ділиться на 3. Ви можете припустити, що головоломка не вирішена

Потім ви вирішите головоломку. Це вимагатиме повторного вибору двох сусідніх плиток для "конвертування" (див. Вище). Ви виведете дві координати цих плиток для кожного кроку, зробленого вашим алгоритмом вирішення. Це також може бути у будь-якому розумному форматі виводу. Ви можете вибирати між індексацією ваших координат на основі 0 та 1 та першими індексувати рядки чи стовпці. Будь ласка, згадайте це у своїй відповіді.

Ваш алгоритм повинен працювати протягом розумного часу в оригінальному випадку 8х8. Насильницьку грубу цілість явно заборонено, тобто ваш алгоритм повинен виконуватись O(k^[m*(n-1)+(m-1)*n])із kкількістю кроків, необхідних для рішення. Однак рішення не повинно бути оптимальним. Доказ, наданий у зв’язаному запитанні, може дати вам уявлення, як це зробити (наприклад, спочатку робіть усі стовпці, використовуючи лише вертикально сусідні плитки, а потім виконайте всі рядки)

Тестові справи

У цих тестових випадках координати базуються на 1, а рядки індексуються спочатку (як MATLAB / Octave та, ймовірно, багато інших).

Input: 
[1 2]
Output: (result: all 3's)
[1 1],[1,2]


Input:
[ 1 2
  3 1 ]
Output: (result: all 1's)
[1 1],[2 1]        (turn left column into 2's)
[2 1],[2 2]        (turn right column into 3's)
[1 1],[1 2]        (turn top row into 1's)
[2 1],[2 2]        (turn bottom row into 1's)

Input:
[1 2 3 2
 3 2 1 1]

Output: (result: all 3's)
[1 1],[1 2] 
[1 3],[1 4] 
[1 2],[1 3] 
[1 1],[1 2] 
[1 2],[1 3] 
[1 1],[1 2]
[1 3],[1 4]
[2 1],[2 2]
[1 1],[2 1]
[1 2],[2 2]
[1 3],[2 3]
[1 4],[2 4]

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


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

@Mego Я, безумовно, вважав це. Однак я боюся, що це перетвориться на DFS або BFS, які запускатимуться назавжди ; або, щоб запобігти цьому, набір нечітких обмежень (наприклад, "повинен працювати протягом години", який надає перевагу людям з масовим комп'ютером або вимагає від мене тестування всіх рішень). І, крім того, в поточному виклику є нульові відповіді запасних мін, тож я сумніваюся, що ще більш складна версія, що вимагає евристики тощо, виявиться більш популярною ... Але, можливо, якщо цей виклик набере обертів, я можу поставити перед собою проблему з братами, як ви описати.
Санчіз

Думаю, я спробую це зробити в Луї, але це може бути довше, ніж рішення 324 байтів ^^
Katenkyo

@Katenkyo Єдиний спосіб дізнатися! Я з нетерпінням чекаю вашого рішення.
Санчіз

Вам доведеться трохи сумно почекати, вам завадило жорстоке рішення, тому я маю знайти рішення, яке не вистачає у луа: p
Katenkyo

Відповіді:


5

Рубін, 266 байт

Більш-менш просто порт рішення Octave, за винятком того, що він вирішує перші рядки замість стовпців. Введення - це масив масивів, внутрішні масиви - це рядки. Вихідні ходи є [row, column, row, column]. Тестовий набір

->m{t=->v{v.size*v.inject(:+)%3}
s=->a,x,r{g=t[a]
(q=(r=0..a.size-2).find{|i|a[i]!=a[i+1]&&g!=a[i]}||r.find{|i|a[i]!=a[i+1]}
a[q,2]=[t[a[q,2]]]*2
p r ?[x,q,x,q+1]:[q,x,q+1,x])while[]!=a-[g]}
m.size.times{|i|s[m[i],i,1]}
m=m.shift.zip *m
m.size.times{|i|s[m[i],i,p]}}

Непорочний з поясненням

->m{                                  # Start lambda function, argument `m`
  t=->v{v.size*v.inject(:+)%3}        # Target color function
  s=->a,x,r{                          # Function to determine proper moves
                                      #   a = row array, x = row index, r = horizontal
    g=t[a]                            # Obtain target color
    (
      q=(r=0..a.size-2).find{|i|      # Find the first index `i` from 0 to a.size-2 where...
        a[i]!=a[i+1]                  # ...that element at `i` is different from the next...
        &&g!=a[i]                     # ...and it is not the same as the target color
      } || r.find{|i|a[i]!=a[i+1]}    # If none found just find for different colors
      a[q,2]=[t[a[q,2]]]*2            # Do the color flipping operation
      p r ?[x,q,x,q+1]:[q,x,q+1,x]    # Print the next move based on if `r` is truthy
    ) while[]!=a-[g]}                 # While row is not all the same target color, repeat
m.size.times{|i|                      # For each index `i` within the matrix's rows...
  s[m[i],i,1]                         # ...run the solving function on that row
                                      #   (`r` is truthy so the moves printed are for rows)
}
m=m.shift.zip *m                      # Dark magic to transpose the matrix
m.size.times{|i|s[m[i],i,p]}}         # Run the solving function on all the columns now
                                      #   (`r` is falsy so the moves printed are for columns)

Цікаво побачити, що порт між двома мовами для гольфу все ще може скласти приблизно 20% різниці. Не могли б ви додати коротке пояснення? (Особливо рядок 3 - я таємно сподіваюся, що я можу це використати у своїй відповіді, оскільки intersectце таке об'ємне ключове слово)
Sanchises

@sanchises було додано пояснення. Щодо того intersect, я не знаю, чи зможете ви виправити це так, як працює моя, оскільки Ruby в findосновному працює на функціях, а ваше functionключове слово так само об'ємне.
Значення чорнила

Я насправді все-таки можу використовувати ваш метод для find- дякую! І все-таки ніде тебе не побили ...
Санчіз

13

Октава, 334 313 байт

Оскільки виклик може здатися трохи непростим, я представляю власне рішення. Я формально не довів, що цей метод працює (я думаю, це зводиться до доведення, що алгоритм ніколи не застрягне в циклі), але поки він працює чудово, роблячи тести 100x100 тестів протягом 15 секунд. Зауважте, що я вирішив використовувати функцію з побічними ефектами, а не з тією, яка повертає всі координати, оскільки це врятувало мені кілька байтів. Координати є основними рядками, на основі 1 та відформатовані як row1 col1 row2 col2. Кольори введення, 0,1,2оскільки це краще працює mod, за рахунок використання, numelа не використання nnz. Версія для гольфу: Редагувати: зберегло ще кілька байтів, використовуючи техніку з відповіді Кевіна Лау.

function P(p)
k=0;[m,n]=size(p);t=@(v)mod(sum(v)*numel(v),3);for c=1:n
p(:,c)=V(p(:,c));end
k=1;for r=1:m
p(r,:)=V(p(r,:));end
function a=V(a)
while any(a-(g=t(a)))
isempty(q=find(diff(a)&a(1:end-1)-g,1))&&(q=find(diff(a),1));
a([q q+1])=t(a([q q+1]));if k
disp([r q r q+1])
else
disp([q c q+1 c])
end;end;end;end

Приклад GIF алгоритму вирішення:

введіть тут опис зображення

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

function solveChromaticPuzzle(p)
[m,n]=size(p);                           % Get size
t=@(v)mod(sum(v)*numel(v),3);            % Target colour function
for c=1:n                                % Loop over columns
    p(:,c)=solveVec(p(:,c));             % Solve vector
end
for r=1:m                                % Loop over rows
    p(r,:)=solveVec(p(r,:));
end
    function a=solveVec(a)               % Nested function to get globals
        g=t(a);                          % Determine target colour
        while(any(a~=g))                 % While any is diff from target...
            % Do the finding magic. Working left-to-right, we find the
            % first pair that can be flipped (nonzero diff) that does not
            % have the left colour different from our goal colour
            q=min(intersect(find(diff(a)),find(a~=g)));
            if(isempty(q))               % In case we get stuck...
                q=find(diff(a),1);       % ... just flip the first possible
            end;
            a([q q+1])=t(a([q q+1]));    % Do the actual flipping.
            if(exist('r'))               % If we're working per row
                disp([r q r q+1])        % Print the pair, using global row
            else
                disp([q c q+1 c])        % Print the pari, using global col
            end
        end
    end
end

Щойно зауважив, але мене не звуть Кенні Лау ... це інший користувач, і моє ім’я користувача спеціально говорить, що я не Кенні
Value Ink

7

Луа, 594 575 559 байт

Попередження Перед тим, як я закінчу з цим гольфу, ще багато роботи! Я мав би вміти брати щонайменше 500 байт. На даний момент це перше рішення, яке спрацювало, і я все ще працюю над цим.

Я надам повне пояснення, як тільки я закінчу.

function f(t)s=#t a=","for i=1,s do p=t[i]for i=1,s
do p.Q=p.Q and p.Q+p[i]or p[i]end p.Q=(p.Q*#p)%3 for i=1,s do for j=1,#p-1 do
x=p[j]y=p[j+1]u=x~=y and(p.S and p.R==p.S or x~=p.Q)v=(x+y)*2p[j]=u and v%3or x
p[j+1]=u and v%3or y print(i..a..j,i..a..j+1)end
p.R=p.S p.S=table.concat(p)end end
for i=1,s do Q=Q and Q+t[i][1]or t[i][1]end Q=(Q*s)%3 for i=1,s
do for j=1,s-1 do p=t[j]q=t[j+1]x=p[1]y=q[1]u=x~=y and(S and R==S or x~=Q)v=(x+y)*2
for k=1,#p do p[k]=u and v%3or x q[k]=u and v%3or y
print(j..a..k,j+1..a..k)end Y=Y and Y..x or x end
R=S S=Y end end

5

Іржа, 496 495 байт

На жаль, я не можу перемогти ОП, але для відповіді Іржі я цілком задоволений рахунком.

let s=|mut v:Vec<_>,c|{
let p=|v:&mut[_],f,t|{
let x=|v:&mut[_],i|{
let n=v[i]^v[i+1];v[i]=n;v[i+1]=n;
for k in f..t+1{print!("{:?}",if f==t{(k,i,k,i+1)}else{(i,k,i+1,k)});}};
let l=v.len();let t=(1..4).find(|x|l*x)%3==v.iter().fold(0,|a,b|a+b)%3).unwrap();
let mut i=0;while i<l{let c=v[i];if c==t{i+=1;}else if c==v[i+1]{
let j=if let Some(x)=(i+1..l).find(|j|v[j+1]!=c){x}else{i-=1;i};x(v,j);}else{x(v,i);}}t};
p(&mut (0..).zip(v.chunks_mut(c)).map(|(i,x)|{p(x,i,i)}).collect::<Vec<_>>(),0,c-1usize)};

Введення: вектор чисел, а також кількість стовпців. Напр

s(vec!{1,2,1,3},2);

виходи

 (row1,col1,row2,col2)

до командного рядка.

Я спочатку вирішую кожен рядок, а потім розв'язую отриманий стовпчик лише один раз, але друкую кроки для всіх стовпців. Тож насправді це досить ефективно :-P.

З форматуванням:

let s=|mut v:Vec<_>,c|{  
    let p=|v:&mut[_],f,t|{     // solves a single row/column
        let x=|v:&mut[_],i|{   // makes a move and prints it 
            let n=v[i]^v[i+1]; // use xor to calculate the new color
            v[i]=n;
            v[i+1]=n;
            for k in f..t{
                print!("{:?}",if f==t{(k,i,k,i+1)}else{(i,k,i+1,k)});
            }
        };
        let l=v.len();
        // find target color
        // oh man i am so looking forward to sum() being stabilized
        let t=(1..4).find(|x|(l*x)%3==v.iter().fold(0,|a,b|a+b)%3).unwrap();
        let mut i=0;
        while i<l{
            let c=v[i];
            if c==t{             // if the color is target color move on
                i+=1;
            }else if c==v[i+1]{ // if the next color is the same
                                // find the next possible move
                let j=if let Some(x)=(i+1..l).find(|j|v[j+1]!=c){x}else{i-=1;i};
                x(v,j);
            }else{              // colors are different so we can make a move
                x(v,i);         
            }
        }
        t
    };
    // first solve all rows and than sovle the resulting column c times 
    p(&mut (0..).zip(v.chunks_mut(c)).map(|(i,x)|p(x,i,i)).collect::<Vec<_>>(),0,c-1usize)
};

Змінити: тепер повертає колір розчину, який зберігає мені крапку з комою ^^


5

Befunge , 197 368 696 754 байт


(так, я роблю гольф із зворотним кодом, чим більше байтів, тим краще)


Я думав, що можна написати цей алгоритм у Befunge, і що це може бути цікаво

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

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


Що ще зроблено: код у формі троля

&:19p&:09p:v:p94g92g90  <
 v94+1:g94&_$59g1+59p1-:|
 >p59gp1-: ^    vp95g93$<
v94\-1<v:g<     >  v
>g:1+v^_$v^90p94g92<
v5p94<   3>1+59p   ^
>9gg+\:^ %g   v93:g95<           v3_2         v
v1pg95g94<^95<>g-v>$v^           v ^-%3*2\gg9<
>9g39g+59g-1-|v-1_^ #^pg95+g92g90<1_09g:29g+5^
       ;  >  >  09g:29g+59gg\3%-# !^v         <
          ^p95<                  ^  <
     v  p96-1+g90g92<
     v                  p95_@
            >59g1+:39g-19g-^
     v    >p 79g:59gg\1+59gp$$$$$29g49pv
    > p59g^ |<<<<<<<<<<<<<<<<<<!-g96g94<
>:79^>29g49p>69g1+59gg49g:59gg\1+49p- v
^\-\6+gg95+1\g< v         !-g96:<-1g94_^
>"]",52*,::59g^v_::1+59gg\59gg-v^ <
^ .-g93g95,.-g<>:69g- v  v-g96:_1+^
>+" [,]",,,\29^       >#v_$:49g2-v
^1:.-g93g95,.-g92\,"[ ":<        <

(так, повірте)


В основному, він зчитує масив і обчислює хід, який потрібно зробити, щоб вирішити рядки, задавши введення як

(number of rows) (number of columns) 1 2 3 1 1 3 2 1 2 ....

(весь масив передається у вигляді списку [рядок1, рядок2, рядок3,…])

вихід є

[col row],[col',row']
[col2 row2],[col2',row2']
...

Обидва рядки та знаки починаються з 0.


Тепер, коли рядки вирішені, це майже зроблено! Ура!


Пояснення: (буде оновлено пізніше)

зображення

Отже, є 5 основних частин:

  • Перший зеленим кольором зчитує рядок введення та записує один рядок масиву
  • Другий, помаранчевим кольором, переходить до наступного ряду масиву
  • Третя, синьою, підсумовує ряд
  • Четвертий, у гарячому рожевому кольорі, бере модуль 3 суми, зберігає його праворуч від відповідного ряду та переходить до наступного ряду
  • Нарешті, у червоному - частина, яка обчислює цільовий колір із раніше обчисленого числа. Ця частина справді німа і її, ймовірно, слід переписати, але я не зрозумів, як мені це вдалося зробити гарним чином (перейшов із 197 байт до 368 саме з цією частиною)

Сірі частини - це ініціалізація


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

                                       B
            @                          v
            |                  !-g96g94<
ENTRY>29g49p>69g1+59gg49g:59gg\1+49p- v
                v         !-g96:<-1g94_^
               v_::1+59gg\59gg-v^ <
               >:69g- v  v-g96:_1+^
                      >#v_$:49g2-v
                    CALL<        <

Частина CALL - це коли вказівник інструкції збирається на інший модуль, який потрібно об'єднати в поля. Він повертається до цього модуля через запис "B"

Ось декілька псевдокодів: (currentx пов'язаний з читанням масиву) Для:

    69g1+59gg  // read target color
    49g:59gg\1+49p // read current color and THEN shift the currentx to the next box
    if ( top != top ){  // if the current color is bad
        49g1-          //  put the current place  (or currentx - 1) in the stack
        While:
            if ( :top != 69g ){   // if you didn't reach the end of the list
                ::1+              // copy twice, add 1
                if ( 59gg == \59gg ){ // if the next color is the same than current
                   1+                // iterate
                   break While;
                }
            }

        : // copies j (the previous raw iterator)
        if ( top == 69g ){  // if you reached the end of the row (which mean you can't swap with the color after that point)
            $:              // discard j's copy and copy target
            49g2-           // put the place just before the color change on the stack
            combine_with_next;
        } else {
            combine_with_next;
        }
        29g49p   // back to the beginning of the row (there was some changes int the row)
    }

    if ( 49g != 69g ) // if you didn't reach the end of the list
        break For:

Зауважте, що якщо ви хочете протестувати його, вам доведеться поставити деякий простір прослуховування та нові рядки, щоб було достатньо місця для зберігання масиву, якщо ви хочете використовувати інтерпретацію, яку я пов’язав. 22 + кількість рядків, що вводяться, як кінцеві лінії, і 34 + кількість стовпців як пробілів на одному рядку має бути нормальним.


Просто цікаво, чому це неконкуренто?
Значення чорнила

Через цю частину: "Я хотів би, щоб це була програма громади". Я подумав, що інакше мене трохи
обдурять

У мене результат 197 байт, ви працюєте під вікнами? (і рахується \r\nзамість \nлише?)
Катенкьо

Гм, напевно, я копіюю приклеєні деякі пробіли під час підрахунку байтів, дякую
Maliafo

Якщо врешті-решт я єдиний, хто це зробив, я
стираю

2

C, 404 байти

Мій перший гольф з кодом, я дуже задоволений тим, як виявилося. Хоча шлях занадто довгий, хоча. Це не повністю стандартний C, все, що складеться під gcc без спеціальних прапорів (і ігнорування попереджень). Отже, там є вкладена функція. Функція fприймає розміри mі nв якості своїх перших аргументів, а як третій аргумент приймає (int pointer) до масиву розміру m× n(індексується спочатку рядками). Інші аргументи - це фіктивні аргументи, вам не потрібно їх передавати, вони просто там, щоб зберегти байти на оголошенні змінних. Він записує кожну змінену пару до STDOUT у форматі row1,col1:row1,col1;, крапкою з комою розділяються пари. Використовує індексацію на основі 0.

#define A a[i*o+p
#define B A*c
f(m,n,a,i,j,o,p,b,c,d)int*a;{
int t(x){printf("%d,%d:%d,%d;",b?i:c+x,b?c+x:i,b?i:c+1+x,b?c+1+x:i);}
o=n;p=b=1;for(;~b;b--){
for(i=0;i<m;i++){c=j=0;
for(;j<n;)c+=A*j++];d=c*n%3;
for(j=0;j<n-1;j++) 
while(A*j]^d|A*j+p]^d){
for(c=j;B]==B+p];c++);
if(c<n-2&B]==d&2*(B+p]+A*(c+2)])%3==d)
B+p]=A*(c+2)]=d,t(1);else
B]=B+p]=2*(B]+B+p])%3,
t(0);}}o=m;p=m=n;n=o;o=1;}}

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

for j in range [0, rowlength):
    while row[j] != targetCol or row[j+1] != targetCol:
        e=j
        while row[e] == row[e+1]:
            e++             //e will never go out of bounds
        if e<=rowLength-3 and row[e] == targetCol 
                and (row[e+1] != row[e+2] != targetCol):
            row.changeColor(e+1, e+2)
        else:
            row.changeColor(e, e+1)

У for(;~b;b--)виконанні циклу рівно в два рази, на другому проході він вирішує стовпці замість рядків. Це робиться шляхом заміни nта mта зміни значень oта, pякі використовуються в арифметиці вказівника для адреси масиву.

Ось версія, яка не має волі, з тестовим основним, і друкує весь масив після кожного ходу (натисніть клавішу Enter для кроку 1 виток):

#define s(x,y)b?x:y,b?y:x
#define A a[i*o+p
#define B A*e
f(m,n,a,i,j,o,p,b,c,d,e)int*a;{

    int t(x){
        printf("%d,%d:%d,%d;\n",s(i,e+x),s(i,e+1+x));
        getchar();
        printf("\n");
        for(int i2=0;i2<(b?m:n);i2++){
            for(int j2=0;j2<(b?n:m);j2++){
                printf("%d ",a[i2*(b?n:m)+j2]);
            }
            printf("\n");
        }
        printf("\n");
    }

    printf("\n");
    b=1;
    for(int i2=0;i2<(b?m:n);i2++){
        for(int j2=0;j2<(b?n:m);j2++){
            printf("%d ",a[i2*(b?n:m)+j2]);
        }
        printf("\n");
    }
    printf("\n");

    o=n;p=1;
    for(b=1;~b;b--){
        for(i=0;i<m;i++){
            c=0;
            for(j=0;j<n;j++) c+= a[i*o+p*j];
            d=0;
            d = (c*n)%3;
            for(j=0;j<n-1;j++) {
                while(a[i*o+p*j]!=d||a[i*o+p*j+p]!=d){
                    for(e=j;a[i*o+p*e]==a[i*o+p*e+p];e++);
                    if(e<=n-3 && a[i*o+p*e]==d 
                            && 2*(a[i*o+p*e+p]+a[i*o+p*(e+2)])%3==d){
                        a[i*o+p*e+p]=a[i*o+p*(e+2)]=d;
                        t(1);
                    }else{
                        a[i*o+p*e]=a[i*o+p*e+p] = 2*(a[i*o+p*e]+a[i*o+p*e+p])%3;
                        t(0);
                    }
                }
            }
        }
        o=m;p=m=n;n=o;o=1;
    }
}

main(){
    int g[11][11] = 
    {
        {0,2,1,2,2,1,0,1,1,0,2},
        {2,1,1,0,1,1,2,0,2,1,0},
        {1,0,2,1,0,1,0,2,1,2,0},
        {0,0,2,1,2,0,1,2,0,0,1},
        {0,2,1,2,2,1,0,0,0,2,1},
        {2,1,1,0,1,1,2,1,0,0,2},
        {1,0,2,1,0,1,0,2,2,1,2},
        {0,0,2,1,2,0,1,0,1,2,0},
        {1,2,0,1,2,0,0,2,1,2,0},
        {2,1,1,0,1,1,2,1,0,0,2},
        {0,2,1,0,1,0,2,1,0,0,2},
    };
    #define M 4
    #define N 7
    int grid[M][N];
    for(int i=0;i<M;i++) {
        for(int j=0;j<N;j++) {
            grid[i][j] = g[i][j];
        }
    }
    f(M,N,grid[0],0,0,0,0,0,0,0,0);
};

Лише з цікавості: чому ви вибрали інший алгоритм (з точки зору економії байтів)?
Санчіз

1
Я думаю, що цікавіше, коли люди придумують різні рішення, і за деякими швидкими тестами я припустив, що два методи будуть приблизно однаковими в кількості байтів. Я, мабуть, спробую і ваш алгоритм і побачу, чи можу я знизитися.
Norg74

Опублікуйте це тут, тому що у мене недостатньо респондентів, щоб прокоментувати це питання. Чи було б дійсним грубі зусилля кожного ряду, а потім кожного стовпця окремо? Це технічно не є «грубим насильством» повністю і повинно бути нижче визначеної часової складності. Я насправді думав це робити.
Norg74

Звертання, що викликає жорстокість, мали на меті посилити зауваження про «розумний час», тому розгляньте це як t «O (...). Я знаю, що між жорстокою силою та розумним алгоритмом є сіра зона, тому використовуйте власне судження про те, чи вважаєте ви, що він працює на вирішення головоломки, чи це лише незначна модифікація на DFS або BFS, які є агностиком "прогресу", так би мовити .
Санчіз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.