Школьная загадка про сейф, которая ставит в тупик большинство взрослых
vk f t

Школьная загадка про сейф, которая ставит в тупик большинство взрослых

Но не про­грам­ми­стов.

На собе­се­до­ва­ни­ях в круп­ные ком­па­нии любят зада­вать мате­ма­ти­че­ские задач­ки. Обыч­ные люди пыта­ют­ся решить их на листах бума­ги, но, если вла­деть про­сты­ми тех­ни­че­ски­ми навы­ка­ми, вы смо­же­те най­ти ответ за секун­ду. Для нача­ла — зада­ча:

Отец умер, и всё его иму­ще­ство пере­шло к жене и детям. Сре­ди иму­ще­ства был сейф, где он дер­жал свои самые важ­ные бума­ги и дра­го­цен­но­сти. Детям страш­но хоте­лось попасть в этот сейф.
У сей­фа был сек­рет: если непра­виль­но вве­сти шифр, всё содер­жи­мое сра­зу сжи­га­ет­ся. Сам кодо­вый замок выгля­дел как квад­рат из 16 яче­ек, в кото­рые нуж­но вве­сти чис­ла.
Дети назва­ли несколь­ко чисел, кото­рые они запом­ни­ли, под­смат­ри­вая за отцом, но осталь­ных они не зна­ли. Мать вспом­ни­ла стран­ность отцов­ско­го шиф­ра: сум­ма всех чисел по каж­дой гори­зон­та­ли, вер­ти­ка­ли и двум глав­ным диа­го­на­лям рав­ня­лась 50. Всё услож­ня­лось тем, что мож­но было вво­дить толь­ко чис­ла от 5 до 20 без повто­ре­ний — осо­бен­ность семей­но­го сей­фа.

Помо­ги­те род­ствен­ни­кам вве­сти недо­ста­ю­щие чис­ла с пер­во­го раза, ина­че всё наслед­ство будет уни­что­же­но систе­мой без­опас­но­сти сей­фа.

Решение

Обыч­но люди реша­ют эту зада­чу про­стым пере­бо­ром: под­став­ля­ют циф­ры в раз­ные ячей­ки и ищут то их соче­та­ние, кото­рое будет соот­вет­ство­вать всем усло­ви­ям.

Но пере­бор — это иде­аль­ная зада­ча для ком­пью­те­ра. Напи­шем про­стой алго­ритм, кото­рый пере­бе­рёт все вари­ан­ты кодов и най­дёт нуж­ное соче­та­ние.

Решим эту зада­чу мето­дом пол­но­го пере­бо­ра. Это зна­чит, что мы по оче­ре­ди будем под­став­лять вме­сто иксов на кар­тин­ке все чис­ла в диа­па­зоне от 5 до 20 в каж­дую ячей­ку, а потом про­ве­рять, выпол­ня­ют­ся усло­вия зада­чи или нет.

Мат­часть про мас­си­вы

Для реше­ния нам пона­до­бит­ся новый тип пере­мен­ной — мас­сив.

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

Cтел­ла­жи — при­мер одно­мер­но­го мас­си­ва. Одно­мер­но­го — зна­чит, что вам неваж­но, на какой кон­крет­ной пол­ке лежит чес­нок, доста­точ­но знать, что он на стел­ла­же номер 0. На стел­ла­же номер 1 — кон­фе­ты, а под номе­ром 2 — стел­лаж с чаем. Это­го доста­точ­но, что­бы послать груз­чи­ка за чаем, если вам неваж­но, какой чай он при­не­сёт. Одно­мер­ность озна­ча­ет, что нам нуж­но знать один толь­ко номер стел­ла­жа, без номе­ров полок.

Дву­мер­ный мас­сив — когда важ­но назвать груз­чи­ку не толь­ко номер стел­ла­жа, но и номер пол­ки, с кото­ро­го взять чай. Трёх­мер­ный — когда нужен ещё и номер нуж­ной под­соб­ки и так далее. Чем слож­нее систе­ма раз­ме­ще­ния про­дук­тов на скла­де, тем мно­го­мер­нее мас­сив. Если нуж­ный нам чай хра­нит­ся в самой пер­вой под­соб­ке на вто­ром стел­ла­же, а в нём — на чет­вёр­той пол­ке, то на язы­ке JavaScript это бы выгля­де­ло так:

Склад[ подсобка_0 ][ стеллаж_1 ][ полка_3 ] = 'чай байховый';

Не забы­вай­те, что всё счи­та­ет­ся начи­ная с нуля, поэто­му пер­вая под­соб­ка пре­вра­ти­лась в подсобку_0, а чет­вёр­тая пол­ка — в полку_3.

Прак­ти­ка с мас­си­ва­ми

Давай­те посмот­рим на при­ме­ры в JavaScript. Нач­нём с одно­мер­но­го мас­си­ва из шести целых чисел:

var massiv = [4,6,1,3,5,2];

Что­бы выве­сти такой мас­сив на экран, исполь­зу­ем цикл от 0 до 5 — все­го 6 шагов. Помни­те, что нуме­ра­ция в мас­си­вах начи­на­ет­ся с нуля:

for (var i = 0; i < 6; i++) {

 

// каждый элемент массива — на новой строке

console.log(massiv[i]);

}

Теперь давай­те попро­бу­ем сде­лать дву­мер­ный мас­сив. В нём пер­вым будет идти чис­ло, вто­рым — назва­ние это­го чис­ла по-русски:

var massiv_2 = [

[1,'Один'],

[2,'Два'],

[3,'Три'],

[4,'Четыре'],

[5,'Пять'],

[6,'Шесть'],

]

Что­бы выве­сти, напри­мер, сло­во «Один», нам нужен эле­мент под номе­ром 0 (нуме­ра­ция — с нуля, а не с еди­ни­цы), а в нём — ячей­ка под номе­ром 1:

console.log(massiv_2[0][1]);

А что­бы выве­сти чис­ло 5 — чет­вёр­тый эле­мент, нуле­вая ячей­ка:

console.log(massiv_2[4][0]);

Давай­те выве­дем на экран все зна­че­ния всех яче­ек наше­го дву­мер­но­го мас­си­ва. Для это­го возь­мём вло­жен­ный цикл: пер­вый будет отве­чать за номе­ра эле­мен­тов, вто­рой — за номе­ра яче­ек:

    
language: JavaScript
//i — номер элемента, от 0 до 5
for (var i = 0; i < 6; i++) {
  //j — номер ячейки, от 0 до 1
  for(var j =0; j <2; j++){
    //на каждом шаге цикла значения i и j меняются
    console.log(massiv_2[i][j]);
  }
}


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Вот так про­сто рабо­тать с мас­си­ва­ми. Теперь мы можем исполь­зо­вать их для реше­ния нашей зада­чи.

Решение: объявляем переменные

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

var code=[
[0,15,0,5],
[17,0,11,0],
[0,0,0,0],
[14,9,0,0],
];

Смот­ри­те, наш мас­сив — дву­мер­ный и состо­ит как бы из строк и столб­цов. Зная это, мы можем рабо­тать с каж­дым эле­мен­том мас­си­ва как с ячей­кой таб­ли­цы. Заве­дём отдель­ные пере­мен­ные для цик­лов:

var i1,i2,i3,i4,i5,i6,i7,i8,i9,i10;

И сде­ла­ем отдель­ную пере­мен­ную, кото­рая будет сле­дить, нашли мы реше­ние или нет. Сде­ла­ем её сна­ча­ла нуле­вой, а как толь­ко най­дём ком­би­на­цию — запи­шем в неё еди­ни­цу. Если к кон­цу рабо­ты про­грам­мы в пере­мен­ной так и оста­нет­ся ноль, зна­чит, реше­ния мы не нашли и сейф нам не открыть.

var code_exist=0;

Логика работы и цикл

Реше­ние будет таким:

  1. Так как мы не зна­ем 10 чисел в шиф­ре, сде­ла­ем 10 вло­жен­ных цик­лов и будем из них брать зна­че­ния для под­ста­нов­ки.
  2. Под­став­ля­ем эти зна­че­ния в наш шифр.
  3. Про­ве­ря­ем все усло­вия, кото­рые есть в зада­че.
  4. Если все усло­вия выпол­ни­лись — выво­дим резуль­тат и поме­ча­ем в пере­мен­ной, что реше­ние най­де­но.

Так как у нас 10 неиз­вест­ных чисел, нам пона­до­бит­ся 10 цик­лов, вло­жен­ных друг в дру­га. Это нуж­но для того, что­бы пере­брать все воз­мож­ные ком­би­на­ции. По усло­вию, чис­ла лежат в диа­па­зоне от 5 до 20 вклю­чи­тель­но, но в таб­ли­це уже есть чис­ло 5 и повто­рять­ся оно не может. Зна­чит, нам нужен диа­па­зон помень­ше — от 6 до 20.

Сде­ла­ем 10 вло­жен­ных цик­лов, исполь­зуя отдель­ную пере­мен­ную для каж­до­го цик­ла. Не забы­вай­те, нам нуж­ны цик­лы с чис­лом 20 вклю­чи­тель­но, поэто­му усло­вие цик­ла — пере­мен­ная долж­на быть мень­ше 21.

    
language: JavaScript
for (i1 = 6; i1 < 21; i1++) {
  for(i2 =6; i2 <21; i2++) {
    for(i3 =6; i3 <21; i3++) {
      for(i4 =6; i4 <21; i4++) {
        for(i5 =6; i5 <21; i5++) {
          for(i6 =6; i6 <21; i6++) {
            for(i7 =6; i7 <21; i7++) {
              for(i8 =6; i8 <21; i8++) {
                for(i9 =6; i9 <21; i9++) {
                  for(i10 =6; i10 <21; i10++) {
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
console.log('i1= ' + i1);
}


Ско­пи­ро­вать код
Код ско­пи­ро­ван

В пред­по­след­нем цик­ле мы доба­ви­ли вывод теку­ще­го зна­че­ния пере­мен­ной i1. Это свя­за­но с тем, что пол­ный пере­бор — ресур­со­ём­кая зада­ча, кото­рая может зани­мать десят­ки минут. Что­бы не было ощу­ще­ния, что ком­пью­тер завис, будем по оче­ре­ди выво­дить зна­че­ние пер­вой пере­мен­ной — её изме­не­ние пока­жет, что зада­ча всё ещё реша­ет­ся.

Все осталь­ные коман­ды будем поме­щать внутрь само­го послед­не­го, деся­то­го цик­ла.

Подстановка значений в шифр

После каж­до­го шага берём зна­че­ния всех пере­мен­ных и под­став­ля­ем их на нуж­ные места вме­сто нулей в наш шифр. Помни­те, что нуме­ра­ция строк и столб­цов начи­на­ет­ся с нуля, а не с еди­ни­цы:

code[0][0]=i1;
code[0][2]=i2;
code[1][1]=i3;
code[1][3]=i4;
code[2][0]=i5;
code[2][1]=i6;
code[2][2]=i7;
code[2][3]=i8;
code[3][2]=i9;
code[3][3]=i0;

Проверяем полученное решение

На каж­дом шаге цик­ла нуж­но про­ве­рять, соот­вет­ству­ет ли наше реше­ние началь­ным усло­ви­ям. Напом­ним усло­вия:

Сде­ла­ем все эти про­вер­ки внут­ри одно­го усло­вия. Нач­нём с про­вер­ки всех гори­зон­та­лей:

(code[0][0]+code[0][1]+code[0][2]+code[0][3] == 50) && 
(code[1][0]+code[1][1]+code[1][2]+code[1][3] == 50) && 
(code[2][0]+code[2][1]+code[2][2]+code[2][3] == 50) && 
(code[3][0]+code[3][1]+code[3][2]+code[3][3] == 50)

Затем вер­ти­ка­лей:

(code[0][0]+code[1][0]+code[2][0]+code[3][0] == 50) && 
(code[0][1]+code[1][1]+code[2][1]+code[3][1] == 50) && 
(code[0][2]+code[1][2]+code[2][2]+code[3][2] == 50) && 
(code[0][3]+code[1][3]+code[2][3]+code[3][3] == 50)

Про­ве­рим диа­го­на­ли:

(code[0][0]+code[1][1]+code[2][2]+code[3][3] == 50) &&
(code[0][3]+code[1][2]+code[2][1]+code[3][0] == 50)

И про­ве­рим, что­бы не было двух оди­на­ко­вых чисел. Для это­го по оче­ре­ди срав­ним каж­дое зна­че­ние эле­мен­та шиф­ра со все­ми осталь­ны­ми по оче­ре­ди. Этот код не очень эле­гант­ный, но делать эле­гант­но сей­час не хочет­ся, ведь мы хотим заста­вить рабо­тать маши­ну, а не себя.

Неэле­гант­ная про­вер­ка уни­каль­но­сти

    
language: JavaScript
(code[0][0] != code[0][1]) &&  (code[0][0] != code[0][2]) && (code[0][0] != code[0][3]) && (code[0][0] != code[1][0]) && (code[0][0] != code[1][1]) && (code[0][0] != code[1][2]) && (code[0][0] != code[1][3]) && (code[0][0] != code[2][0]) && (code[0][0] != code[2][1]) && (code[0][0] != code[2][2]) && (code[0][0] != code[2][3]) && (code[0][0] != code[3][0]) && (code[0][0] != code[3][1]) && (code[0][0] != code[3][2]) && (code[0][0] != code[3][3]) && 

 

(code[0][1] != code[0][2]) && (code[0][1] != code[0][3]) && (code[0][1] != code[1][0]) && (code[0][1] != code[1][1]) && (code[0][1] != code[1][2]) && (code[0][1] != code[1][3]) && (code[0][1] != code[2][0]) && (code[0][1] != code[2][1]) && (code[0][1] != code[2][2]) && (code[0][1] != code[2][3]) && (code[0][1] != code[3][0]) && (code[0][1] != code[3][1]) && (code[0][1] != code[3][2]) && (code[0][1] != code[3][3]) && 

 

(code[0][2] != code[0][3]) && (code[0][2] != code[1][0]) && (code[0][2] != code[1][1]) && (code[0][2] != code[1][2]) && (code[0][2] != code[1][3]) && (code[0][2] != code[2][0]) && (code[0][2] != code[2][1]) && (code[0][2] != code[2][2]) && (code[0][2] != code[2][3]) && (code[0][2] != code[3][0]) && (code[0][2] != code[3][1]) && (code[0][2] != code[3][2]) && (code[0][2] != code[3][3]) && 

 

(code[0][3] != code[1][0]) && (code[0][3] != code[1][1]) && (code[0][3] != code[1][2]) && (code[0][3] != code[1][3]) && (code[0][3] != code[2][0]) && (code[0][3] != code[2][1]) && (code[0][3] != code[2][2]) && (code[0][3] != code[2][3]) && (code[0][3] != code[3][0]) && (code[0][3] != code[3][1]) && (code[0][3] != code[3][2]) && (code[0][3] != code[3][3]) && 

 

(code[1][0] != code[1][1]) && (code[1][0] != code[1][2]) && (code[1][0] != code[1][3]) && (code[1][0] != code[2][0]) && (code[1][0] != code[2][1]) && (code[1][0] != code[2][2]) && (code[1][0] != code[2][3]) && (code[1][0] != code[3][0]) && (code[1][0] != code[3][1]) && (code[1][0] != code[3][2]) && (code[1][0] != code[3][3]) && 

 

(code[1][1] != code[1][2]) && (code[1][1] != code[1][3]) && (code[1][1] != code[2][0]) && (code[1][1] != code[2][1]) && (code[1][1] != code[2][2]) && (code[1][1] != code[2][3]) && (code[1][1] != code[3][0]) && (code[1][1] != code[3][1]) && (code[1][1] != code[3][2]) && (code[1][1] != code[3][3]) && 

 

(code[1][2] != code[1][3]) && (code[1][2] != code[2][0]) && (code[1][2] != code[2][1]) && (code[1][2] != code[2][2]) && (code[1][2] != code[2][3]) && (code[1][2] != code[3][0]) && (code[1][2] != code[3][1]) && (code[1][2] != code[3][2]) && (code[1][2] != code[3][3]) && 

 

(code[1][3] != code[2][0]) && (code[1][3] != code[2][1]) && (code[1][3] != code[2][2]) && (code[1][3] != code[2][3]) && (code[1][3] != code[3][0]) && (code[1][3] != code[3][1]) && (code[1][3] != code[3][2]) && (code[1][3] != code[3][3]) && 

 

(code[2][0] != code[2][1]) && (code[2][0] != code[2][2]) && (code[2][0] != code[2][3]) && (code[2][0] != code[3][0]) && (code[2][0] != code[3][1]) && (code[2][0] != code[3][2]) && (code[2][0] != code[3][3]) && 

 

(code[2][1] != code[2][2]) && (code[2][1] != code[2][3]) && (code[2][1] != code[3][0]) && (code[2][1] != code[3][1]) && (code[2][1] != code[3][2]) && (code[2][1] != code[3][3]) && 

 

(code[2][2] != code[2][3]) && (code[2][2] != code[3][0]) && (code[2][2] != code[3][1]) && (code[2][2] != code[3][2]) && (code[2][2] != code[3][3]) && 

 

(code[2][3] != code[3][0]) && (code[2][3] != code[3][1]) && (code[2][3] != code[3][2]) && (code[2][3] != code[3][3]) && 

 

(code[3][0] != code[3][1]) && (code[3][0] != code[3][2]) && (code[3][0] != code[3][3]) && 

 

(code[3][1] != code[3][2]) && (code[3][1] != code[3][3]) && 

 

(code[3][2] != code[3][3])


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Выводим правильную комбинацию

Сей­час наш услов­ный опе­ра­тор пустой: если все усло­вия выпол­нят­ся, то всё рав­но ниче­го не про­изой­дёт. Давай­те это испра­вим и доба­вим вывод реше­ния на экран:

console.log('Unlocked!');
console.log(code[0][0]+' '+code[0][1]+' '+code[0][2]+' '+code[0][3]);
console.log(code[1][0]+' '+code[1][1]+' '+code[1][2]+' '+code[1][3]);
console.log(code[2][0]+' '+code[2][1]+' '+code[2][2]+' '+code[2][3]);
console.log(code[3][0]+' '+code[3][1]+' '+code[3][2]+' '+code[3][3]);

Собираем код в одно целое

Что­бы про­грам­ма рабо­та­ла пра­виль­но, надо все коман­ды запи­сать в нуж­ной после­до­ва­тель­но­сти:

Ито­го­вый код

    
language: JavaScript
var code = [
[0,15,0,5],
[17,0,11,0],
[0,0,0,0],
[14,9,0,0],
];

 

var i1, i2, i3, i4, i5, i6, i7, i8, i9, i10;
var code_exist = 0;

 

for (i1 = 6; i1 < 21; i1++) {
for(i2 =6; i2 <21; i2++){
for(i3 =6; i3 <21; i3++){
for(i4 =6; i4 <21; i4++){
for(i5 =6; i5 <21; i5++){
for(i6 =6; i6 <21; i6++){
for(i7 =6; i7 <21; i7++){
for(i8 =6; i8 <21; i8++){
for(i9 =6; i9 <21; i9++){
for(i10 =6; i10 <21; i10++){

 

code[0][0] = i1;
code[0][2] = i2;
code[1][1] = i3;
code[1][3] = i4;
code[2][0] = i5;
code[2][1] = i6;
code[2][2] = i7;
code[2][3] = i8;
code[3][2] = i9;
code[3][3] = i10;

 

if(

 

(code[0][0]+ code[0][1]+ code[0][2]+ code[0][3]==50)&&
(code[1][0]+ code[1][1]+ code[1][2]+ code[1][3]==50)&&
(code[2][0]+ code[2][1]+ code[2][2]+ code[2][3]==50)&&
(code[3][0]+ code[3][1]+ code[3][2]+ code[3][3]==50)&&

 

(code[0][0]+ code[1][0]+ code[2][0]+ code[3][0]==50)&&
(code[0][1]+ code[1][1]+ code[2][1]+ code[3][1]==50)&&
(code[0][2]+ code[1][2]+ code[2][2]+ code[3][2]==50)&&
(code[0][3]+ code[1][3]+ code[2][3]+ code[3][3]==50)&&

 

(code[0][0]+ code[1][1]+ code[2][2]+ code[3][3]==50)&&
(code[0][3]+ code[1][2]+ code[2][1]+ code[3][0]==50)&&

 

(code[0][0]!= code[0][1])&&(code[0][0]!= code[0][2])&&(code[0][0]!= code[0][3])&&(code[0][0]!= code[1][0])&&(code[0][0]!= code[1][1])&&(code[0][0]!= code[1][2])&&(code[0][0]!= code[1][3])&&(code[0][0]!= code[2][0])&&(code[0][0]!= code[2][1])&&(code[0][0]!= code[2][2])&&(code[0][0]!= code[2][3])&&(code[0][0]!= code[3][0])&&(code[0][0]!= code[3][1])&&(code[0][0]!= code[3][2])&&(code[0][0]!= code[3][3])&&

 

(code[0][1]!= code[0][2])&&(code[0][1]!= code[0][3])&&(code[0][1]!= code[1][0])&&(code[0][1]!= code[1][1])&&(code[0][1]!= code[1][2])&&(code[0][1]!= code[1][3])&&(code[0][1]!= code[2][0])&&(code[0][1]!= code[2][1])&&(code[0][1]!= code[2][2])&&(code[0][1]!= code[2][3])&&(code[0][1]!= code[3][0])&&(code[0][1]!= code[3][1])&&(code[0][1]!= code[3][2])&&(code[0][1]!= code[3][3])&&

 

(code[0][2]!= code[0][3])&&(code[0][2]!= code[1][0])&&(code[0][2]!= code[1][1])&&(code[0][2]!= code[1][2])&&(code[0][2]!= code[1][3])&&(code[0][2]!= code[2][0])&&(code[0][2]!= code[2][1])&&(code[0][2]!= code[2][2])&&(code[0][2]!= code[2][3])&&(code[0][2]!= code[3][0])&&(code[0][2]!= code[3][1])&&(code[0][2]!= code[3][2])&&(code[0][2]!= code[3][3])&&

 

(code[0][3]!= code[1][0])&&(code[0][3]!= code[1][1])&&(code[0][3]!= code[1][2])&&(code[0][3]!= code[1][3])&&(code[0][3]!= code[2][0])&&(code[0][3]!= code[2][1])&&(code[0][3]!= code[2][2])&&(code[0][3]!= code[2][3])&&(code[0][3]!= code[3][0])&&(code[0][3]!= code[3][1])&&(code[0][3]!= code[3][2])&&(code[0][3]!= code[3][3])&&

 

(code[1][0]!= code[1][1])&&(code[1][0]!= code[1][2])&&(code[1][0]!= code[1][3])&&(code[1][0]!= code[2][0])&&(code[1][0]!= code[2][1])&&(code[1][0]!= code[2][2])&&(code[1][0]!= code[2][3])&&(code[1][0]!= code[3][0])&&(code[1][0]!= code[3][1])&&(code[1][0]!= code[3][2])&&(code[1][0]!= code[3][3])&&

 

(code[1][1]!= code[1][2])&&(code[1][1]!= code[1][3])&&(code[1][1]!= code[2][0])&&(code[1][1]!= code[2][1])&&(code[1][1]!= code[2][2])&&(code[1][1]!= code[2][3])&&(code[1][1]!= code[3][0])&&(code[1][1]!= code[3][1])&&(code[1][1]!= code[3][2])&&(code[1][1]!= code[3][3])&&

 

(code[1][2]!= code[1][3])&&(code[1][2]!= code[2][0])&&(code[1][2]!= code[2][1])&&(code[1][2]!= code[2][2])&&(code[1][2]!= code[2][3])&&(code[1][2]!= code[3][0])&&(code[1][2]!= code[3][1])&&(code[1][2]!= code[3][2])&&(code[1][2]!= code[3][3])&&

 

(code[1][3]!= code[2][0])&&(code[1][3]!= code[2][1])&&(code[1][3]!= code[2][2])&&(code[1][3]!= code[2][3])&&(code[1][3]!= code[3][0])&&(code[1][3]!= code[3][1])&&(code[1][3]!= code[3][2])&&(code[1][3]!= code[3][3])&&

 

(code[2][0]!= code[2][1])&&(code[2][0]!= code[2][2])&&(code[2][0]!= code[2][3])&&(code[2][0]!= code[3][0])&&(code[2][0]!= code[3][1])&&(code[2][0]!= code[3][2])&&(code[2][0]!= code[3][3])&&

 

(code[2][1]!= code[2][2])&&(code[2][1]!= code[2][3])&&(code[2][1]!= code[3][0])&&(code[2][1]!= code[3][1])&&(code[2][1]!= code[3][2])&&(code[2][1]!= code[3][3])&&

 

(code[2][2]!= code[2][3])&&(code[2][2]!= code[3][0])&&(code[2][2]!= code[3][1])&&(code[2][2]!= code[3][2])&&(code[2][2]!= code[3][3])&&

 

(code[2][3]!= code[3][0])&&(code[2][3]!= code[3][1])&&(code[2][3]!= code[3][2])&&(code[2][3]!= code[3][3])&&

 

(code[3][0]!= code[3][1])&&(code[3][0]!= code[3][2])&&(code[3][0]!= code[3][3])&&

 

(code[3][1]!= code[3][2])&&(code[3][1]!= code[3][3])&&

 

(code[3][2]!= code[3][3])

 

){

 

console.log('Unlocked!');

 

console.log(code[0][0]+' '+ code[0][1]+' '+ code[0][2]+' '+ code[0][3]);

 

console.log(code[1][0]+' '+ code[1][1]+' '+ code[1][2]+' '+ code[1][3]);

 

console.log(code[2][0]+' '+ code[2][1]+' '+ code[2][2]+' '+ code[2][3]);

 

console.log(code[3][0]+' '+ code[3][1]+' '+ code[3][2]+' '+ code[3][3]);
}
}
}
}
}
}
}
}
}
}
console.log('i1= '+ i1);
}


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Запускаем код в браузере

Запус­ка­ем бра­у­зер Chrome и вызы­ва­ем кон­соль ком­би­на­ци­ей кла­виш Shift+Ctrl+I. Встав­ля­ем наш код в кон­соль, нажи­ма­ем Enter. Через несколь­ко минут вы уви­ди­те нача­ло рабо­ты про­грам­мы — нач­нёт­ся вывод зна­че­ний пере­мен­ной i1. Как толь­ко ком­пью­тер под­бе­рёт реше­ние — тут же выве­дет его на экран и про­дол­жит рабо­ту. Если реше­ние не поме­сти­лось на экране — про­сто про­кру­ти­те вывод резуль­та­тов наверх.

И ТУТ ПРИБЕГАЮТ НАСТОЯЩИЕ ПРОГРАММИСТЫ и кричат «ПЛОХОЙ КОД!»

Тот код, кото­рый у нас полу­чил­ся — при­ми­тив­ный, пло­хо выгля­дит и вызы­ва­ет силь­ное жела­ние его опти­ми­зи­ро­вать. Давай­те пере­пи­шем кусок кода с про­вер­ка­ми, где мы в лоб срав­ни­ва­ем эле­мен­ты мас­си­ва меж­ду собой и про­ве­ря­ем таким же обра­зом сум­му эле­мен­тов в стро­ках.

Опти­ми­зи­ро­ван­ный для чте­ния код

    
language: JavaScript
// сигнальные переменные, которые следят за тем, все ли условия выполняются. По умолчанию они говорят, что всё верно, но внутри кода, как только будет ошибка при проверке, они превратятся в ложные
var diag = true;
var lines = true;
var uniqie = true;
 
// здесь мы будем хранить результат вычислений сумм, равны они 50 или нет
var result1, result2, result3, result4 = 0;
 
// проверяем обе диагонали
for (var j = 0; j < 4; j++){
result1 += code[j][j];
result2 += code[j][3-j];
}
 
// если хоть одно из них не 50 — помечаем, что условие не выполнилось
if ((result1 != 50) && (result2 != 50)){diag = false};
 
// проверяем сумму в строках и столбцах
for (var j = 0; j < 4; j++){
for (var k = 0; k < 4; k++){
 
// суммируем строку и столбец
result3 += code[j][k];
result4 += code[k][j];
}
 
// если сумма не та, что нужно — помечаем, что условие в линиях не выполнилось
if (result3 != 50){lines = false};
if (result4 != 50){lines = false};
 
// здесь же — сравниваем каждый элемент массива со всеми остальными
for (j1 = j; j1 < 4; j1++){
for (k1 = k; k1 < 4; k1++){
 
// если нашли равные элементы — помечаем, что эта проверка провалилась
if (code[j][k] == code[j1][k1]) {uniqie = false};
}
}
}
 
// если все проверки прошли успешно — выводим результат
if (diag && lines && uniqie){
 
console.log('Unlocked!');
console.log(code[0][0]+' '+code[0][1]+' '+code[0][2]+' '+code[0][3]);
console.log(code[1][0]+' '+code[1][1]+' '+code[1][2]+' '+code[1][3]);
console.log(code[2][0]+' '+code[2][1]+' '+code[2][2]+' '+code[2][3]);
console.log(code[3][0]+' '+code[3][1]+' '+code[3][2]+' '+code[3][3]);
 
}


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Код стал чита­бель­нее, ушли гро­мад­ные про­вер­ки эле­мен­тов мас­си­ва, но этот код стал выпол­нять­ся в 40-50 раз мед­лен­нее, чем ста­рый! Дело в том, что у нас при про­вер­ке появи­лось несколь­ко двой­ных цик­лов, а в месте, где мы про­ве­ря­ем эле­мен­ты мас­си­ва на уни­каль­ность — аж 4 вло­жен­ных цик­ла. При этом они все рас­по­ла­га­ют­ся внут­ри деся­ти­крат­но вло­жен­но­го цик­ла, кото­рый сам по себе — доста­точ­но ресур­со­ём­кая вещь.

Поэто­му, не все­гда нуж­но опти­ми­зи­ро­вать код, кото­рый внешне выгля­дит некра­си­во. Если на пер­вом месте — быст­ро­дей­ствие, то ино­гда гру­бый код рабо­та­ет быст­рее, чем кра­си­вый. Такие дела.

А где ответ на задачу?

А отве­та не будет 🙂 Что­бы его узнать, запу­сти­те код само­сто­я­тель­но. Напри­мер, через кон­соль бра­у­зе­ра. И дожди­тесь, когда код выдаст пра­виль­ный ответ.

Что дальше

Код, кото­рый у нас полу­чил­ся, — не самый кра­си­вый и быст­рый, его мож­но опти­ми­зи­ро­вать несколь­ки­ми спо­со­ба­ми. Напри­мер, отка­зать­ся от про­ме­жу­точ­но­го запол­не­ния пере­мен­ной code и срав­ни­вать зна­че­ния пере­мен­ных напря­мую. Есть и дру­гие, более изящ­ные спо­со­бы орга­ни­за­ции пол­но­го пере­бо­ра.

Ещё по теме