Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование с нуля - это совсем просто! 26) Чулки, Фанта и структурное программирование Дейкстры


Информационный Канал Subscribe.Ru

 
Школа программирования

Программирование с нуля - это совсем просто!

26) Чулки, Фанта и структурное программирование Дейкстры

Сначала про чулки. Только те письма, в которых есть объяснения, засчитываются.

Кстати, пожалуйста указывайте в своих письмах хотя бы имя.
Клички, ники - они у ежиков, это не крутость, а глупость :)
А мы люди вроде.

С каждым вытаскиванием сочетание белых и черных чулок может быть любым (в пределах 20 штук каждого цвета)
Таким образом, чтобы гарантированно получить
а) 1 пару чулок любого (одного) цвета?
Нужно 3 чулка. Т.к. в после второго вытаскивания у нас имеется либо уже пара, либо два чулка разных цветов, и тогда какой бы мы ни вытащили третьим, будет пара.
б) 1 пару белых?
Нужно 22 чулка. Т.к. в «наихудшем» варианте перед тем, как вытащить второй белый, придется вытащить все 20 черных.
в) 2 пары чулок?
Нужно 5 чулок. Т.к. после четвертого вытаскивания имеем либо уже 2 пары, либо 3 чулка одного цвета и один другого. Тогда после пятого в любом случае получаем 2 пары.
г) 2 пары чулок, все одного цвета?
Нужно 7 чулок, т.к. нам нужно вытащить четвертый чулок одного цвета, а это будет самое большее на седьмой раз, если до этого мы вытащим по три каждого цвета.
д) 2 пары различного цвета?
Нужно 22 чулка, если вдруг нам придется перед тем, как вытащить второй чулок какого-либо цвета, сначала вытащить все двадцать другого цвета.
е) 2 пары белых чулок?
Нужно 24 чулка. Тут объяснение аналогично, т.е. если перед четвертым белым вытащим все черные.
ж) 5 пар чулок?
11 чулок. Т.к. из любых 10 будут либо пять пар, либо четыре пары и еще по одному чулку каждого цвета, тогда одиннадцатый образует пятую пару.
з) 3 пары белых и 2 пары черных?
26 чулок, если перед тем, как вытащить шестой белый, вытащим все 20 черных.
Ольга

Ответ на задачку о чулках:
а) 3; потому как цветов 2 и в любом случае, как не тяни, получится
одна пара; б+б+ч, ч+б+ч, ч+ч+б ...
б) 22; здесь посложнее потому что можно при определенной везучести :) вытягивать подряд все черные, и только когда они закончатся добавляем 2 и гарантировано получаем одну белую пару;
в) 5; аналогично варианту а): б+б+ч+ч+ч, б+ч+б+ч+б ... в любых случаях две пары;
г) 7; трудно пояснить, если в варианте в) мы имеем 2 пары любого цвета то для 2 пар одного цвета нужно добавить еще 2 чулка;
д) 22; аналогично варианту б): 20ч - одна пара ч и +2 одна пара б; е) 24; аналогично вариантам б) и д);
ж) 11; варианты а),в),г) прослеживается закономерность: если нужно х пар чулок не определенного цвета то х*2+1 это количество чулок которые надо вытянуть;
з) 26; исходим из худшего попадают все черные, будет 20 и добавим 3 пары белых.
Сергей

В задаче по чулкам выводы такие:
а).3 чулок,так как если 2 раза у нас чулки оказались разного цвета,то в 3 раз однозначно получим пару одного цвета.
б).22 чулок,так как в случае самого неблагоприятного исхода мы вытаскиваем все 20 черного цвета,соответственно оставшиеся белого,а их надо 2 единицы.
в).4,так как цвет не указан,а 2 пары-4 штуки.
г).24 штуки,так как при неблагоприятных обстоятельствах вытаскиваем 20 чулок другого цвета,а оставшиеся нужного цвета,а их надо 4 штуки.
д).22 штуки,в неблагоприятном случае вытаскиваем сначала все носки одного цвета,их будет 20,затем остается вытащить пару другого цвета.
е).24,см. пункт г).
ж).10 чулок,так как цвет здесь роли не играет,а пара=2 штуки.
з).26 штук,так как при неблагоприятных обстоятельствах,вытащив нужное количество пар одного цвета,нам могут попадаться и дальше чулки этого же цвета,а их вообщем случае-20 штук.А поскольку белых надо больше,3 пары, поэтому их надо 6 штук.
Константин

a)lyubogo tsveta-3 raza
b)belih-22 raza(v hudshem sluchae posle 20 chernih viidut 2 belih)
c)2 pari-5raz
d)2 pari odnogo tsveta 24 raza(22+2)
e)2 pari razlichnogo 22 raza
f)2 pari belih-24raza
g)5 par 11 raz(3+4*2)
h)3 belih I 2 chernih 26(20+2*3)
Maria

Правильные ответы такие: 3, 22, 5, 7, 22, 24, 11, 26.

Далее - присланные решения алгоритма расчета цены на Фанту. Сказать по правде, я сам не знаю, как она правильно решается :)

Привожу все ответы, поэтому определите сами, верен ваш вариант или нет. Если кто-то сможет дать оценку правильности различным решениям, будет замечательно!

n = 5 ( k - m )
5 — число дней в неделе ( ну, до пятницы )
Самое эффективное решение вроде...
Wizard

имеем следующее решение
1 n равно начальной сумме денег
2 m равно стоимости пустой бутылки
3 k равно стоимости бутылки Фанты
4 Day(Дни недели) равно 0
5 если n деленое на k меньше 1 или Day равен 5 тогда идти к п. 11
6 Sd(сдача) равна остатку от деления n на k
7 увеличиваем Day на 1
8 берем целую часть от деления n на k и запоминаем в x
9 n равно x умноженное на m, плюс Sd
10 идти к п.5
11 если Day равен 5 тогда счтитать решением "Да, денег хватает", иначе
считать решением "Нет, денег не хватает"
12 завершить работу
Art

Мне лично не очень нравится мое решение, т.к. получается простой перебор всех значений, но может быть, в этом есть какое-то «рациональное зерно»?
Сначала определимся с переменными.
a – сумма, которую мы имеем на конкретный момент.
b – число купленных бутылок
c – сдача
d – количество дней
1. d=0 (определяем себя в начало понедельника)
a=n (Это сумма, которую мы имеем на начало понедельника)
2. Вычисляем, сколько бутылок можем купить
b=a/k
Если b<1, то идем к пункту 6.
Если b>1, то к пункту 3.
3. Дробную часть числа b умножаем на k и присваиваем это значение переменной с (сдача), а за переменной b оставляем только целую часть.
4. Высчитываем сумму, которой располагаем на конец дня
a=b*m+c
Выясняем, в конце какого дня мы находимся.
d=d+1
если d=4 переходим к пункту 5.
если d<4, то возвращаемся к пункту 2.
5. Проверяем состояние на конец четверга.
Если a>=k, то ответ = n
Если a<k, то переходим к пункту 6.
6. n=n+1 (повышаем значение n) и идем снова в пункт 1
Ольга

1. Имеются исходные данные: к – стоимость фанты и m – стоимость бутылки.
2. Предполагаем, что начальная сумма не может быть меньше стоимости бутылки с фантой, т.е. первоначально n = k, где n – минимальная сумма.
3. а = 0 – сколько денег на руках утром после сдачи бутылок.
4. До тех пор, пока а < k, выполняем расчеты (утром в пятницу должна быть куплена хотя бы одна бутылка):
a. nn := n – промежуточная переменная.
b. Считаем 4 раза (на вторник, среду, четверг и пятницу):
Определяем кол-во купленных бутылок с фантой w = nn/k.
Определяем остаток денег после покупки бутылок y = nn-w*k.
Определяем а = w*m+y.
1) nn := a.
c. n := n+1
5. Результат находится в переменной n.
Татьяна

Значит,нам нужно декларировать переменные:
"к"-руб-стоимость полной бутылки
"п"-руб-необходимая сумма,которую ищем
"м"-руб-стоимость пустой бутылки
"с"-руб-сдача
ВСЕ РУБЛЕВЫЕ ПЕРЕМЕННЫЕ-ДРОБНЫЕ
"ц"-означает ЦЕЛОЕ число
"х"-тоже ЦЕЛОЕ -это типа счетчик
------------------------------------------------------------
1 х:=1
2 п:=к
3 ц:=п/м
4 с:=п-м*ц
5 п:=ц*к+с
6 х:=х+1
7 если х=5,то -Выход-строчка 9
8 если нет, то переход на строчку 3
9 вывод на экран значения "п"
Проверил на калькуляторе-вроде все сходится.
Alex

У меня огромная радость и невероятное облегчение. Я справилась с этой фантой, правда я не уверенна, что запись правильная, но не суть. Главное я это сделала!!!!!!!! :-).
Начинала рассуждать с начала, с понедельника:
1.Если у них было в понедельник Dп рублей, и они на все купили Хп бутылок по К рублей, значит надо Dп/К , выделить целую часть Хп и найти остаток- сдачу (Yп). Хп- столько бутылок купили в понедельник и сдали во вторник.
2. Во вторник они сдали Хп бутылок по М руб. и добавили сдачу за понедельник Yп, значит у них во вторник было денег: Dв=Хп*М+Yп, На них они купили Хв бутылок( Dв/К, выделить целую часть Хв и найти остаток-сдачу Yв).
3. В среду они сдали Хв бутылок по М рублей, добавили сдачу Yв, и у них получилось Dc=Хв*М+Yв рублей. На них они купили Хс (Dс/К, выделить целую часть и определить остаток-сдачу Yс).
4. В четверг сдали Хс бутылок по М руб., добавили сдачу Yс. Dч=Хс*М+Yс это все деньги в четверг. Купили на них Хч бутылок (Dч/К, выделить целую часть и найти остаток-сдачу Yч).
5. Так как разговор идёт о минимальной необходимой сумме, я предположила, что в пятницу, сдав бутылки, и добавив сдачу у них должно было хватить денег только на одну, и никакой сдачи.
Лена

А попозже Лена прислала и программу!

program Project1;
{$APPTYPE CONSOLE}
var d1,d2,d3,d4,d5,x1,x2,x3,x4,y1,y2,y3,y4,k,m:integer;
begin
writeln( ' vs yunedelyubutylkaFantystoilakrub,apustayabutylkamrub. '
writeln( ' Kompaniya druzei,v ponedelnik, imeya d1 rub, kupila na vse dengi Fantu. ' );
writeln( ' na sleduyuschii den, sdav pustye butylki i dobaviv sdachu, ostavshuyusya s ponedelnika, opyat na vse dengi kupili Fantu. ' );
writeln( ' na sleduyuschii den, postupili tak zhe. ' );
writeln( ' Kakova dolzhna byt minimalnaya summa v ponedelnik, chtoby v pyatnitsu im bylo chto kupit ' );
writeln( ' vvedite stoimost Fanty: ' );
readln(k);
writeln( ' vvedite stoimost pustoi butylki: ' );
readln(m);
d5:=k;
x4:=d5 div m;
y4:=d5 mod m;
d4:=x4*k+y4;
x3:=d4 div m;
y3:=d4 mod m;
d3:=x3*k+y3;
x2:=d3 div m;
y2:=d3 mod m;
d2:=x2*k+y2;
x1:=d2 div m;
y1:=d2 mod m;
d1:=x1*k+y1;
write( ' ponadobitsya ' );
write( d1);
write( ' rub. ' );
readln;
end.

В задаче про друзей-любителей "Фанты" алгоритм такой:
1.разделить n на k и умножить на m,результат (n/k)*m запомнить в x;
2.сравнить k с (n/k)*m(с числом,записанным в x),если K меньше (n/k)*m,то перейти к п.1,т.е. снова разделить число записанное в x на k и умножить на m: (((n/k)*m)/k)*m,иначе перейтик пункту 3.
3.Завершить работу.
Константин.

Пришлось помучится над заданием, в общем, думаю, ответ будет такой:
1)введем стоимость фанты "k";
2)введем стоимость бутылки "m";
3)проверим условие: m<k, если "нет", то идем к п.16, если "да", то:
4)введем количество дней "z" (в нашем случае = 5);
5)проверим условие: Z>=1, если "нет", то идем к п.16, если "да", то:
6)введем некоторое количество денег "n";
7)проверим условие n>k, если "нет", то идем в п.16, если "да", то:
8)вычислим количество фанты, приобретенной в z-ый день:
y=(n*z)/k - берем целую часть от деления;
9)сдача от покупки фанты будет:
x=n-y*k;
10)пусть z=z-1 (на следующий день), то:
11)(y*m+1)/k = y1 - количество фанты, проиобретенной на следующий день - берем целый остаток от деления;
12)проверим условие:
(y1/k)>1 - берем целый остаток;
если "да", то идем к п.8, если "нет", идем к п.16;
13)если z=1 (последний день), то:
14)проверим следующее условие:
(y*m+x)/k = 1;
если "нет", то идем к п.16, если "да", то:
15)"Найдена минимальная сумма n";
16)Завершение программы.
Карлыгаш


Что касается алгоритма, словесного написания инструкции. Тут, гляжу, вольности определенные наметились :) Некоторые начинают уж слишком общие вещи за один шаг выполнять. Ну типа задача "найти минимальное число из трех значений", и некоторые так "алгоритм" записывают:

1. Ввести три числа a, b, c.
2. Найти минимальное число из трех значений.
3. Напечатать результат.
4. Завершить работу.

Надо комментировать, в чем ошибка?

Самое важное. Хотя инструкция словесная, пользоваться в ней можно все равно ограниченным числом команд. Это: ввод и вывод значений, расчет формул, завершение работы. Условное разветвление - если условие, то - и сразу группу команд. Иначе - тоже группу команд. Вот так как-то:

...
п. 8.
Если a > b то
8.1.1 Записать в a значение 1.
8.1.2 Записать в b произведение x и y.

Иначе
8.2.1 Записать в a сумму a и b.

п. 9
...

Многократное выполнение группы пунктов разрешено, либо заданное число раз, либо до некоторого условия.

п. 12. Записать в n число 1.

п. 13. Пока значение n меньше 100, выполнять:
13.1 Прибавить к значению a значение n в квадрате.
13.2 Увеличить значение n на 1.
13.3 Если остаток от деления n на 7 равен нулю, напечатать значение n.

п. 14 ...

Здесь выполняется, пока n < 100, группа команд 13.1, 13.2, 13.3. Как выполнится многократно, начнется 14-й пункт, но не раньше.

Или так:

п. 22. Выполнять, пока x-координата ежика меньше 100:
22.1 Сдвинуть ежика вправо на три клетки.
22.2 Увеличить его x-координату на 3.
22.3 Если в текущей клетке, где ежик, есть яблоко, то:
22.3.1 Увеличить СчетчикЯблок на единицу.
22.3.2 Удалить яблоко из данной клетки

п.23 ...

Доказано математически - с помощью условной команды, команды многократного выполнения группы других команд (так называемый цикл), и команды вычисления некоторого значения (присваивание) можно запрограммировать ЛЮБОЙ алгоритм. Хоть автоматизация бухгалтерии, хоть игра в шахматы.

Никаких других команд больше не нужно. В языках программирования их побольше немного, но только для удобства так сделано. А достаточно этих трех. А мы еще добавим команду завершения работы алгоритма.

п. 99.
Если ежик дома, то завершить алгоритм.

п. 100
Если на клетке с ежиком хомяк, то ...
(вступить в схватку! :-) если хомяк победил, то завершить алгоритм).

В прошлом примере с инструкцией, когда две одинаковых цифры надо было определить в числе, если помните, инструкция эта записывалась немного по другому. В частности, была в ней такая , гадкая :) команда, как Перейти к п. XXX. Оператор перехода так называемый. Вроде бы вещь полезная на первый взгляд, а на самом деле крайне вредная! Никогда им не пользуйтесь!

Как только логика программы усложняется, от перехода только вред один остается. Потому что ненаглядно получается, неясно, что, как, почему. Выполнялась-выполнялась программа, и вдруг бах! - надо куда-то совсем в сторону уходить. Чуть посложнее код создается, и переход его почти всегда портит.

Этоо уже методологические вещи. Как правильно алгоритмы составлять. Лучше сразу учиться делать это качественно, оптимально. Есть такое классическое, фундаментальное! структурное программирование, предложенное легендарной личностью в программировании Э. Дейкстрой.

Его идея в том, что программа всегда выполняется последовательно, блок за блоком, группа за группой. А внутри каждый блок тоже представляется в виде последовательных команд. То есть нельзя взять, и из одной группы в другую перескочить. Поэтому структура программы получается очень стройной и прозрачной. Сделал одно, другое, третье - и результат. А не так, чтобы сделал одно, потом другое, потом вдруг прыгнул опять к первому, потом сразу на четвертое, оттуда на второе...

Поэтому в наших алгоритмах-инструкциях использовать команду перехода к другому пункту ЗАПРЕЩЕНО! Ясно?

Тогда перепишем ее примерно следующим макаром:

1. Ввести два числа a, b.

2. В x записать сумму a + b.

3. Если в числе x меньше двух цифр, то
3.1. Напечатать "нет".
3.2 Завершить алгоритм.

4. В n записать число 2.

5. Выполнять следующую группу команд, пока значение n меньше или равно числу цифр в числе x.

5.1 Если цифра числа x с номером n равна цифре с номером n-1, то
5.1.1 Напечатать "есть".
5.1.2 Завершить алгоритм.

5.2 Увеличить значение n на 1.

6. Напечатать "нет".

7. Завершить алгоритм.

Обратили внимание, что в данном тексте происходит только прямое, последовательное выполнение групп команд? А раньше из-за команд перехода к разным пунктам логика алгоритма была плохо понятной.

С ежиками алгоритмы конечно нагляднее получаются :) Ну я буду стараться подбирать, подходящие задачки.

Еще несколько заданий на условный оператор.

6. Решаем квадратное уравнение. Помните, как?

y = ax2 + by + c.

Дискриминант сначала считаем:
D = b2 - 4ac;

Корни: x1 = (-b+ корень из (d))/2a;
x2 = (-b- корень из (d))/2a.

Если дискриминант меньше нуля, то корней быть не может. Также, если a = 0. Вроде :)

Если D = 0, то будет одно решение.

Корень в Дельфи так считается - sqrt( );

x := sqrt( 2*2 );

В Си - она также записывается, библиотеку math.h только надо подключить.

7. Есть параллелепипед :) со сторонами x, y, z. Надо выяснить, войдет ли он хоть как-нибудь :) в паз размером w, h.
Условимся, что только параллельно стенкам паза его можно вводить.

Собственно, те, кто добрался до данного упражнения и делает программки, уже готовый программист. Раз вы разобрались с типами данных, переменными, оператором присваивания и условным оператором, то дальше уже будет в основном техника программирования. Оператор цикла остается (в следующем занятии), но это уже проще, чем раньше, будет в изучении.

На машине можно ездить, вспотев и вцепившись ручками в руль, а можно - расслабившись и поглядывая по сторонам, ведя автомобиль автоматически. Но и в первом случае человек уже едет ! Неуверенно, плохо (пока!), но ЕДЕТ.

Можете себя поздравить :)


(c) 2004 Сергей Бобровский bobrovsky@russianenterprisesolutions.com

Школа программирования с нуля
http://russianenterprisesolutions.com/sbo/

Все предыдущие выпуски базового курса тут:
http://russianenterprisesolutions.com/sbo/base.htm

 

http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.prognull
Отписаться

В избранное