Попал программист в больницу, и началось

Задач­ка, куда ж без нее.

В одну боль­ни­цу при­вез­ли сто­лит­ро­вую фля­гу 96-процентного спир­та и такую же фля­гу дистил­ли­ро­ван­ной воды. По инструк­ции сотруд­ни­ки долж­ны про­ти­рать все при­бо­ры 40-процентным рас­тво­ром спир­та, а гряз­ной посу­дой поль­зо­вать­ся нель­зя. Един­ствен­ное, что было чистое в отде­ле­нии, — лит­ро­вая круж­ка. А запас сво­бод­но­го места в каж­дой фля­ге был как раз один литр.

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

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

Но вот как эту зада­чу решит про­грам­мист. 

РЕШЕНИЕ

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

Теперь выяс­ним, за какой фля­гой нам надо сле­дить. Если мы даже мог­ли бы пере­ме­шать обе фля­ги, то общая кон­цен­тра­ция полу­чи­лась бы 48%, а это боль­ше, чем нуж­но. Зна­чит, нам нуж­но повы­шать кон­цен­тра­цию спир­та во вто­рой фля­ге с водой и сле­дить за её зна­че­ни­ем.

Наша зада­ча — понять, как меня­ет­ся кон­цен­тра­ция спир­та в каж­дой фля­ге после пере­ли­ва­ния, и научить­ся это использовать.Обозначим кон­цен­тра­цию спир­та в пер­вой фля­ге К1, а во вто­рой — К2. Если пер­вым дви­же­ни­ем мы пере­ли­ва­ем спирт в воду, то кон­цен­тра­ция спир­та во вто­рой фля­ге будет такая:

К2 = (К1 + 100 × К2) / 101

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

После обрат­но­го пере­ли­ва­ния из вто­рой в первую кон­цен­тра­ция спир­та в пер­вой фля­ге будет такая:

К1 = (К2 + 99 × К1) / 100

Это зна­чит, что мы берём кон­цен­тра­цию лит­ра из вто­рой фля­ги, добав­ля­ем его к осталь­ным 99 лит­рам в пер­вой фля­ге и делим на общее коли­че­ство лит­ров.

Смот­ри­те, на каж­дом сле­ду­ю­щем шаге пере­ли­ва­ния будут повто­рять­ся, поэто­му мы можем ска­зать, что на каж­дом нечёт­ном шаге (1,3,5…) мы будем менять кон­цен­тра­цию К2, пото­му что пере­ли­ва­ем во вто­рую фля­гу. А на каж­дом чёт­ном пере­ли­ва­нии будем менять кон­цен­тра­цию К1 в пер­вой фля­ге.

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

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

    
language: JavaScript
// переменные для концентрации и счётчик переливаний
var k1, k2, i;
 
// задаём начальные концентрации
k1 = 0.96;
k2 = 0;
 
// пока не было ни одного переливания
i = 0;
 
// переливаем до тех пор, пока не получится нужная концентрация
while ( k2 <= 0.4) {
 
// увеличиваем количество переливаний
i += 1;
 
// если чётное — меняем концентрацию первой бочки
if (i % 2 == 0) {k1 = (k2 + 99 * k1) / 100}
 
// если нет — то второй
else {k2 = (k1 + 100 * k2) / 101};
}
 
// выводим количество переливаний, когда цикл остановится
console.log(i);

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

Когда запу­стим код, уви­дим, что нам нуж­но оста­но­вить­ся после 179-го пере­ли­ва­ния.