Существует классическая задача:
Есть 2 емкости: 5 литров и 3 литра. Как отмерить 4 литра жидкости используя только эти 2 емкости?
Понятное дело что тут важно не сколько знание правильного ответа, а знание метода решения таких задач. Ведь вместо целевых 4х литров могут спросить отсчитать и 1,2,6,7 литров.
В этом тексте я решу эту задачу в общем виде при помощи конечного автомата. Так как тут явно можно проследить состояния и входные воздействия. Также я упомяну про малоизвестный язык Front-End разметки Dot. Методика конечного автомата хорошо изучена и поставлена на рельсы. Состоит из 3 фаз.
Фаза №1: перечислить все возможные состояния (комбинаторика)
Состояние определяется количеством жидкости в паре сосудов. Согласно комбинаторике по правилу умножения существует всего 24 состояния. Вот они все перечислены.
Фаза №2 перечислить все возможные входы. (из условий задачи)
Существует всего 5 легальных действий с бутылками. Вот их перечень.
Фаза №3 составить таблицу переходов
+----+-----+-----+-----+-----+-----+-----+-----+
| # | | E0 | E1 | T0 | T0 | 0T1 | 1T0 |
+----+-----+-----+-----+-----+-----+-----+-----+
| 1 | s00 | s00 | s00 | s50 | s03 | s00 | s00 |
| 2 | s01 | s01 | s00 | s51 | s03 | s01 | s10 |
| 3 | s02 | s02 | s00 | s52 | s03 | s02 | s20 |
| 4 | s03 | s03 | s00 | s53 | s03 | s03 | s30 |
| 5 | s10 | s00 | s10 | s50 | s13 | s01 | s10 |
| 6 | s11 | s01 | s10 | s51 | s13 | s02 | s20 |
| 7 | s12 | s02 | s10 | s52 | s13 | s03 | s30 |
| 8 | s13 | s03 | s10 | s53 | s13 | s13 | s40 |
| 9 | s20 | s00 | s20 | s50 | s23 | s02 | s20 |
| 10 | s21 | s01 | s20 | s51 | s23 | s03 | s30 |
| 11 | s22 | s02 | s20 | s52 | s23 | s13 | s40 |
| 12 | s23 | s03 | s20 | s53 | s23 | s23 | s50 |
| 13 | s30 | s00 | s30 | s50 | s33 | s03 | s30 |
| 14 | s31 | s01 | s30 | s51 | s33 | s13 | s40 |
| 15 | s32 | s02 | s30 | s52 | s33 | s23 | s50 |
| 16 | s33 | s03 | s30 | s53 | s33 | s33 | s51 |
| 17 | s40 | s00 | s40 | s50 | s43 | s13 | s40 |
| 18 | s41 | s01 | s40 | s51 | s43 | s23 | s50 |
| 19 | s42 | s02 | s40 | s52 | s43 | s33 | s51 |
| 20 | s43 | s03 | s40 | s53 | s43 | s43 | s52 |
| 21 | s50 | s00 | s50 | s50 | s53 | s23 | s50 |
| 22 | s51 | s01 | s50 | s51 | s53 | s33 | s51 |
| 23 | s52 | s02 | s50 | s52 | s53 | s43 | s52 |
| 24 | s53 | s03 | s50 | s53 | s53 | s53 | s53 |
+----+-----+-----+-----+-----+-----+-----+-----+
Фаза №4 отрисовать граф состояний (Helicopter view)
Как гласит английская народная пословица “Картинка стоит тысячи слов” (A picture is worth a thousand words). Также мой универский профессор часто говорил, что инженеры - это про схемы. Поэтому представляю блок-схему в виде ориентированного графа состояний для задачи про бутылки.
Я накропал на языке С консольную утилиту, которая прокручивает конечный автомат и сохраняет в файл составленный код на языке dot. Далее бесплатная утилита dot.exe поедает файл *.dot и преобразует его во всем известный *.svg файл. Наконец браузер Chrome.exe поедает *.svg и отрисовывает в окне на мониторе. Язык Dot хорош тем что он имеет простой синтаксис. Dot более высокоуровневый язык, чем спецификация *.svg файлов.
Глядя на этот ориентированный граф становится очевидным, что чтобы отмерить 4 литра надо выполнить следующую процедуру из 6-ти инструкций:
есть еще одно синее решение
Easy!
Вот код Dot графа для тех, кто захочет изучить граф внимательнее.
digraph G {
b0_5__b0_3_T_0 [label="b0_5__b0_3_T_0" color=grey96 style=filled shape=box];
b0_5__b0_3_T_0->b5_5__b0_3_T_5 [label="Top0" color=Red fontcolor=Red]
b5_5__b0_3_T_5 [label="b5_5__b0_3_T_5" color=grey73 style=filled shape=box];
b5_5__b0_3_T_5->b5_5__b0_3_T_5 [label="Top0" color=Red fontcolor=Red]
b5_5__b0_3_T_5->b5_5__b3_3_T_8 [label="Top1" color=orange fontcolor=orange]
b5_5__b3_3_T_8 [label="b5_5__b3_3_T_8" color=grey55 style=filled shape=box];
b5_5__b3_3_T_8->b5_5__b3_3_T_8 [label="Top0" color=Red fontcolor=Red]
b5_5__b3_3_T_8->b5_5__b3_3_T_8 [label="Top1" color=orange fontcolor=orange]
b5_5__b3_3_T_8->b0_5__b3_3_T_3 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b3_3_T_3 [label="b0_5__b3_3_T_3" color=grey82 style=filled shape=box];
b0_5__b3_3_T_3->b5_5__b3_3_T_8 [label="Top0" color=Red fontcolor=Red]
b0_5__b3_3_T_3->b0_5__b3_3_T_3 [label="Top1" color=orange fontcolor=orange]
b0_5__b3_3_T_3->b0_5__b3_3_T_3 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b3_3_T_3->b0_5__b0_3_T_0 [label="Empty1" color=aqua fontcolor=aqua]
b0_5__b3_3_T_3->b0_5__b3_3_T_3 [label="0->1" color=green fontcolor=green]
b0_5__b3_3_T_3->b3_5__b0_3_T_3 [label="0<-1" color=blue fontcolor=blue]
b3_5__b0_3_T_3 [label="b3_5__b0_3_T_3" color=grey82 style=filled shape=box];
b3_5__b0_3_T_3->b5_5__b0_3_T_5 [label="Top0" color=Red fontcolor=Red]
b3_5__b0_3_T_3->b3_5__b3_3_T_6 [label="Top1" color=orange fontcolor=orange]
b3_5__b3_3_T_6 [label="b3_5__b3_3_T_6" color=grey69 style=filled shape=box];
b3_5__b3_3_T_6->b5_5__b3_3_T_8 [label="Top0" color=Red fontcolor=Red]
b3_5__b3_3_T_6->b3_5__b3_3_T_6 [label="Top1" color=orange fontcolor=orange]
b3_5__b3_3_T_6->b0_5__b3_3_T_3 [label="Empty0" color=royalblue fontcolor=royalblue]
b3_5__b3_3_T_6->b3_5__b0_3_T_3 [label="Empty1" color=aqua fontcolor=aqua]
b3_5__b3_3_T_6->b3_5__b3_3_T_6 [label="0->1" color=green fontcolor=green]
b3_5__b3_3_T_6->b5_5__b1_3_T_6 [label="0<-1" color=blue fontcolor=blue]
b5_5__b1_3_T_6 [label="b5_5__b1_3_T_6" color=grey69 style=filled shape=box];
b5_5__b1_3_T_6->b5_5__b1_3_T_6 [label="Top0" color=Red fontcolor=Red]
b5_5__b1_3_T_6->b5_5__b3_3_T_8 [label="Top1" color=orange fontcolor=orange]
b5_5__b1_3_T_6->b0_5__b1_3_T_1 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b1_3_T_1 [label="b0_5__b1_3_T_1" color=grey91 style=filled shape=box];
b0_5__b1_3_T_1->b5_5__b1_3_T_6 [label="Top0" color=Red fontcolor=Red]
b0_5__b1_3_T_1->b0_5__b3_3_T_3 [label="Top1" color=orange fontcolor=orange]
b0_5__b1_3_T_1->b0_5__b1_3_T_1 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b1_3_T_1->b0_5__b0_3_T_0 [label="Empty1" color=aqua fontcolor=aqua]
b0_5__b1_3_T_1->b0_5__b1_3_T_1 [label="0->1" color=green fontcolor=green]
b0_5__b1_3_T_1->b1_5__b0_3_T_1 [label="0<-1" color=blue fontcolor=blue]
b1_5__b0_3_T_1 [label="b1_5__b0_3_T_1" color=grey91 style=filled shape=box];
b1_5__b0_3_T_1->b5_5__b0_3_T_5 [label="Top0" color=Red fontcolor=Red]
b1_5__b0_3_T_1->b1_5__b3_3_T_4 [label="Top1" color=orange fontcolor=orange]
b1_5__b3_3_T_4 [label="b1_5__b3_3_T_4" color=grey78 style=filled shape=box];
b1_5__b3_3_T_4->b5_5__b3_3_T_8 [label="Top0" color=Red fontcolor=Red]
b1_5__b3_3_T_4->b1_5__b3_3_T_4 [label="Top1" color=orange fontcolor=orange]
b1_5__b3_3_T_4->b0_5__b3_3_T_3 [label="Empty0" color=royalblue fontcolor=royalblue]
b1_5__b3_3_T_4->b1_5__b0_3_T_1 [label="Empty1" color=aqua fontcolor=aqua]
b1_5__b3_3_T_4->b1_5__b3_3_T_4 [label="0->1" color=green fontcolor=green]
b1_5__b3_3_T_4->b4_5__b0_3_T_4 [label="0<-1" color=blue fontcolor=blue]
b4_5__b0_3_T_4 [label="b4_5__b0_3_T_4" color=grey78 style=filled shape=box];
b4_5__b0_3_T_4->b5_5__b0_3_T_5 [label="Top0" color=Red fontcolor=Red]
b4_5__b0_3_T_4->b4_5__b3_3_T_7 [label="Top1" color=orange fontcolor=orange]
b4_5__b3_3_T_7 [label="b4_5__b3_3_T_7" color=grey64 style=filled shape=box];
b4_5__b3_3_T_7->b5_5__b3_3_T_8 [label="Top0" color=Red fontcolor=Red]
b4_5__b3_3_T_7->b4_5__b3_3_T_7 [label="Top1" color=orange fontcolor=orange]
b4_5__b3_3_T_7->b0_5__b3_3_T_3 [label="Empty0" color=royalblue fontcolor=royalblue]
b4_5__b3_3_T_7->b4_5__b0_3_T_4 [label="Empty1" color=aqua fontcolor=aqua]
b4_5__b3_3_T_7->b4_5__b3_3_T_7 [label="0->1" color=green fontcolor=green]
b4_5__b3_3_T_7->b5_5__b2_3_T_7 [label="0<-1" color=blue fontcolor=blue]
b5_5__b2_3_T_7 [label="b5_5__b2_3_T_7" color=grey64 style=filled shape=box];
b5_5__b2_3_T_7->b5_5__b2_3_T_7 [label="Top0" color=Red fontcolor=Red]
b5_5__b2_3_T_7->b5_5__b3_3_T_8 [label="Top1" color=orange fontcolor=orange]
b5_5__b2_3_T_7->b0_5__b2_3_T_2 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b2_3_T_2 [label="b0_5__b2_3_T_2" color=grey87 style=filled shape=box];
b0_5__b2_3_T_2->b5_5__b2_3_T_7 [label="Top0" color=Red fontcolor=Red]
b0_5__b2_3_T_2->b0_5__b3_3_T_3 [label="Top1" color=orange fontcolor=orange]
b0_5__b2_3_T_2->b0_5__b2_3_T_2 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b2_3_T_2->b0_5__b0_3_T_0 [label="Empty1" color=aqua fontcolor=aqua]
b0_5__b2_3_T_2->b0_5__b2_3_T_2 [label="0->1" color=green fontcolor=green]
b0_5__b2_3_T_2->b2_5__b0_3_T_2 [label="0<-1" color=blue fontcolor=blue]
b2_5__b0_3_T_2 [label="b2_5__b0_3_T_2" color=grey87 style=filled shape=box];
b2_5__b0_3_T_2->b5_5__b0_3_T_5 [label="Top0" color=Red fontcolor=Red]
b2_5__b0_3_T_2->b2_5__b3_3_T_5 [label="Top1" color=orange fontcolor=orange]
b2_5__b3_3_T_5 [label="b2_5__b3_3_T_5" color=grey73 style=filled shape=box];
b2_5__b3_3_T_5->b5_5__b3_3_T_8 [label="Top0" color=Red fontcolor=Red]
b2_5__b3_3_T_5->b2_5__b3_3_T_5 [label="Top1" color=orange fontcolor=orange]
b2_5__b3_3_T_5->b0_5__b3_3_T_3 [label="Empty0" color=royalblue fontcolor=royalblue]
b2_5__b3_3_T_5->b2_5__b0_3_T_2 [label="Empty1" color=aqua fontcolor=aqua]
b2_5__b3_3_T_5->b2_5__b3_3_T_5 [label="0->1" color=green fontcolor=green]
b2_5__b3_3_T_5->b5_5__b0_3_T_5 [label="0<-1" color=blue fontcolor=blue]
b2_5__b0_3_T_2->b0_5__b0_3_T_0 [label="Empty0" color=royalblue fontcolor=royalblue]
b2_5__b0_3_T_2->b2_5__b0_3_T_2 [label="Empty1" color=aqua fontcolor=aqua]
b2_5__b0_3_T_2->b0_5__b2_3_T_2 [label="0->1" color=green fontcolor=green]
b2_5__b0_3_T_2->b2_5__b0_3_T_2 [label="0<-1" color=blue fontcolor=blue]
b5_5__b2_3_T_7->b5_5__b0_3_T_5 [label="Empty1" color=aqua fontcolor=aqua]
b5_5__b2_3_T_7->b4_5__b3_3_T_7 [label="0->1" color=green fontcolor=green]
b5_5__b2_3_T_7->b5_5__b2_3_T_7 [label="0<-1" color=blue fontcolor=blue]
b4_5__b0_3_T_4->b0_5__b0_3_T_0 [label="Empty0" color=royalblue fontcolor=royalblue]
b4_5__b0_3_T_4->b4_5__b0_3_T_4 [label="Empty1" color=aqua fontcolor=aqua]
b4_5__b0_3_T_4->b1_5__b3_3_T_4 [label="0->1" color=green fontcolor=green]
b4_5__b0_3_T_4->b4_5__b0_3_T_4 [label="0<-1" color=blue fontcolor=blue]
b1_5__b0_3_T_1->b0_5__b0_3_T_0 [label="Empty0" color=royalblue fontcolor=royalblue]
b1_5__b0_3_T_1->b1_5__b0_3_T_1 [label="Empty1" color=aqua fontcolor=aqua]
b1_5__b0_3_T_1->b0_5__b1_3_T_1 [label="0->1" color=green fontcolor=green]
b1_5__b0_3_T_1->b1_5__b0_3_T_1 [label="0<-1" color=blue fontcolor=blue]
b5_5__b1_3_T_6->b5_5__b0_3_T_5 [label="Empty1" color=aqua fontcolor=aqua]
b5_5__b1_3_T_6->b3_5__b3_3_T_6 [label="0->1" color=green fontcolor=green]
b5_5__b1_3_T_6->b5_5__b1_3_T_6 [label="0<-1" color=blue fontcolor=blue]
b3_5__b0_3_T_3->b0_5__b0_3_T_0 [label="Empty0" color=royalblue fontcolor=royalblue]
b3_5__b0_3_T_3->b3_5__b0_3_T_3 [label="Empty1" color=aqua fontcolor=aqua]
b3_5__b0_3_T_3->b0_5__b3_3_T_3 [label="0->1" color=green fontcolor=green]
b3_5__b0_3_T_3->b3_5__b0_3_T_3 [label="0<-1" color=blue fontcolor=blue]
b5_5__b3_3_T_8->b5_5__b0_3_T_5 [label="Empty1" color=aqua fontcolor=aqua]
b5_5__b3_3_T_8->b5_5__b3_3_T_8 [label="0->1" color=green fontcolor=green]
b5_5__b3_3_T_8->b5_5__b3_3_T_8 [label="0<-1" color=blue fontcolor=blue]
b5_5__b0_3_T_5->b0_5__b0_3_T_0 [label="Empty0" color=royalblue fontcolor=royalblue]
b5_5__b0_3_T_5->b5_5__b0_3_T_5 [label="Empty1" color=aqua fontcolor=aqua]
b5_5__b0_3_T_5->b2_5__b3_3_T_5 [label="0->1" color=green fontcolor=green]
b5_5__b0_3_T_5->b5_5__b0_3_T_5 [label="0<-1" color=blue fontcolor=blue]
b0_5__b0_3_T_0->b0_5__b3_3_T_3 [label="Top1" color=orange fontcolor=orange]
b0_5__b0_3_T_0->b0_5__b0_3_T_0 [label="Empty0" color=royalblue fontcolor=royalblue]
b0_5__b0_3_T_0->b0_5__b0_3_T_0 [label="Empty1" color=aqua fontcolor=aqua]
b0_5__b0_3_T_0->b0_5__b0_3_T_0 [label="0->1" color=green fontcolor=green]
b0_5__b0_3_T_0->b0_5__b0_3_T_0 [label="0<-1" color=blue fontcolor=blue]
b1_5__b1_3_T_2 [label="b1_5__b1_3_T_2" color=grey87 style=filled shape=box];
b1_5__b2_3_T_3 [label="b1_5__b2_3_T_3" color=grey82 style=filled shape=box];
b2_5__b1_3_T_3 [label="b2_5__b1_3_T_3" color=grey82 style=filled shape=box];
b2_5__b2_3_T_4 [label="b2_5__b2_3_T_4" color=grey78 style=filled shape=box];
b3_5__b1_3_T_4 [label="b3_5__b1_3_T_4" color=grey78 style=filled shape=box];
b3_5__b2_3_T_5 [label="b3_5__b2_3_T_5" color=grey73 style=filled shape=box];
b4_5__b1_3_T_5 [label="b4_5__b1_3_T_5" color=grey73 style=filled shape=box];
b4_5__b2_3_T_6 [label="b4_5__b2_3_T_6" color=grey69 style=filled shape=box];
}
Можно отрисовать граф на этом сайте и сохранить его в *.svg.
Редактировать *.svg можно при помощи бесплатной программы Inkscape.exe.
Эта задача может служить отличной иллюстрацией для обучения теории конечных автоматов FSM. Конечные автоматы повсеместно используются в промышленной разработке, например, системного программного обеспечения.
Существует 8 недостижимых состояний: 1/5_1/3; 1/5_2/3; 2/5_1/3; 2/5_2/3; 3/5_1/3; 3/5_2/3; 4/5_1/3; 4/5+2/3. В эти состояния никак не попасть как только не переливай содержимое сосудов. Если вы захотите завалить человека на собеседовании, то можно попросить его "как перелить жидкости так чтобы в каждой бутылине осталось по 2 литра?" или "как перелить жидкости так чтобы в каждой бутылке осталось по 1 литру?".
Формально можно отмерить не только 4 лита, а все значения от 1 до 8 включительно.
Вывод
Как видите, язык Front-End разметки Dot отлично подходит для автоматической отрисовки сложной векторной графики. Конечно dot тула несовершенна и даже планарные графы строит с пересечениями ребер. Если вы знаете тулу которая гарантирует планарность, то укажите это в комментариях.
Буду признателен, если пришлете описания подобного рода логических задач в комментариях к тексту.
Комментарии (29)
vesper-bot
23.04.2022 17:50+4не далее как пару недель назад я пытался написать именно общее (N ведер, X1...XN объемы, вектор начального состояния, вектор целевого состояния) решение задачи с ведрами на Прологе. Не осилил, хотя технически ничего сверхсложного, вроде бы.
А ещё — я не вижу в этой статье вообще ничего содержательного про dot. Только "породил текст прогой на С, скормил его проге на dot, получил SVG". Мало! Как минимум нужно описать, почему вообще dot, а не какая-нибудь утилита для генерации SVG.
kenoma
23.04.2022 21:52+1dot поразительно похож на популярные языки разметки uml типа Mermaid или PlantUML, никогда не ощущал особых проблем при переходе между ними. Ценность dot разве что в том, что рендеринг графа может быть осуществлен с помощью разных средств визуализации и что сам dot может рендерить громадные графы. Правда, ценность последнего сомнительна.
Asparagales
23.04.2022 19:00+2Взять и налить в 5-литровую емкость 5л. жидкости, а затем из нее наполнить 3-литровую емкость. В первой емкости останется два литра. Выливаете жидкость из обоих емкостей и повторяете процесс. Так мы отмеряли 4 л. В условиях задачи не сказано, что эти литры должны быть в этих емкостях, а не на полу, так что все правильно. Если что, ответить вам скоро не смогу из-за кармы. Нет, доту мы не знаем, мы и так эти задачки щелкаем за минуту.
screwer
23.04.2022 19:04+4В крепком орешке именно что сказано - надо было поставить на весы 4кн чтобв отключить бомбу.
Alexashka
23.04.2022 23:05+8Вылить 3л в 5л первый раз, во второй раз в трехлитровой останется 1 литр. Опорожнить пятилитровую. Вылить в нее литр из трешки и налить еще одну трешку.
ramiil
23.04.2022 23:12+7Налить в пятилитровку. Перелить в трёхлитровку. В пятилитровке останется два, вылить на землю из трёхлитровки, налить из пятилитровки оставшиеся два литра в трёшку и снова наполнить пятилитровку. Отлить из пятилитровки в трёхлитровку литр воды. В пятилитровке останется ровно четыре литра.
xaosxaos2
24.04.2022 10:13А если вот так, у вас только две канистры 5л и 3л, наполненные водой, доп. ёмкостей нет, воды другой нет.
randomsimplenumber
24.04.2022 16:36Не всякая задача имеет решение.
MikeLP
24.04.2022 20:44Можно половину 5 литров слить и половину 3 литров слить. :)
randomsimplenumber
24.04.2022 21:35Хорошо тому живётся, кто в уме умеет считать интеграл по объему и у кого глаз-ватерпас ;)
Alexandroppolus
26.04.2022 02:10Половину можно вылить, например, из цилиндрической ёмкости, но в условии ни слова о форме..
Кстати, вспомнилась не совсем стандартная задачка на переливания
Rsa97
23.04.2022 20:35Этот пункт я пропущу так как таблица получится циклопических размеров. По правилу умножения 24*5=120 строк
Таблица получится ровно на 24 строки. Каждая строка содержит все переходы из одного состояния, а состояний у вас 24.
Tyusha
23.04.2022 22:14+1Я так понимаю для состояния возможны действия: наполнить из источника 5, наполнить изисточника 3, слить 5, слить 3, перелить 5 в 3, перелить 3 в 5. Но для некоторых состояний не всё действия возможны, например, когда сосуд пуст, сливать его бессмысленное, нового состояния не возникнет.
Rsa97
24.04.2022 00:46+3Это неважно. Таблица задаёт переходы из состояния в состояние под действием входных символов. Поскольку у нас 24 состояния, то в таблице будет 24 строки. Поскольку у нас 6 входных символов, то в таблице будет 6 колонок переходов плюс колонка исходного состояния.
Обозначим состояния через sXY, где X — количество воды в 5-литровой бутыли, Y — количество воды в 3-литровой. Входные символы (действия) обозначим как E5 — опустошить 5-литровую бутыль, E3 — опустошить 3-литровую, F5 — заполнить 5-литровую, F3 — заполнить трёхлитровую, 5T3 — перелить из 5-литровой в 3-литровую, 3T5 — из 5-литровой в 3-литровую бутыль.
Тогда таблица переходов будет выглядеть так:+-----+-----+-----+-----+-----+-----+-----+ | | E5 | E3 | F5 | F3 | 5T3 | 3T5 | +-----+-----+-----+-----+-----+-----+-----+ | s00 | s00 | s00 | s50 | s03 | s00 | s00 | | s01 | s01 | s00 | s51 | s03 | s01 | s10 | | s02 | s02 | s00 | s52 | s03 | s02 | s20 | | s03 | s03 | s00 | s53 | s03 | s03 | s30 | | s10 | s00 | s10 | s50 | s13 | s01 | s10 | | s11 | s01 | s10 | s51 | s13 | s02 | s20 | | s12 | s02 | s10 | s52 | s13 | s03 | s30 | | s13 | s03 | s10 | s53 | s13 | s13 | s40 | | s20 | s00 | s20 | s50 | s23 | s02 | s20 | | s21 | s01 | s20 | s51 | s23 | s03 | s30 | | s22 | s02 | s20 | s52 | s23 | s13 | s40 | | s23 | s03 | s20 | s53 | s23 | s23 | s50 | | s30 | s00 | s30 | s50 | s33 | s03 | s30 | | s31 | s01 | s30 | s51 | s33 | s13 | s40 | | s32 | s02 | s30 | s52 | s33 | s23 | s50 | | s33 | s03 | s30 | s53 | s33 | s33 | s51 | | s40 | s00 | s40 | s50 | s43 | s13 | s40 | | s41 | s01 | s40 | s51 | s43 | s23 | s50 | | s42 | s02 | s40 | s52 | s43 | s33 | s51 | | s43 | s03 | s40 | s53 | s43 | s43 | s52 | | s50 | s00 | s50 | s50 | s53 | s23 | s50 | | s51 | s01 | s50 | s51 | s53 | s33 | s51 | | s52 | s02 | s50 | s52 | s53 | s43 | s52 | | s53 | s03 | s50 | s53 | s53 | s53 | s53 | +-----+-----+-----+-----+-----+-----+-----+
И откуда тут взять 120 строк?
Survtur
23.04.2022 20:49+3Ой, я видел шикарное видео на канале mathologer - наглядное решение этой задачи в графичечком виде.
VT100
23.04.2022 20:57+1А нет ли у Вас чего-то вроде IAR Visual State(?), чтобы по псевдокоду Dot получить исходник на C? Будет разом и алгоритм и исходник.
mentin
24.04.2022 03:06+1Dot хорош что отличная инфраструктура для разработчиков, на любой платформе. Ну и то что ему лет 50 наверное и всё давно отполировано и исправлено.
Из свежего, для рисования диаграмм популярен Mermaid, его можно скажем вставлять в .md файлы на GitHub.
KaminskyIlya
24.04.2022 09:47+2Такого рода задачи легко решаются при помощи теории групп. Мало того, именно при помощи теории групп вы сможете доказать, что задача вообще имеет решение. Числа 5 и 3 взаимно просты, а значит вы легко сможете получить любое значение: 1, 2, 3, 4, 5 литров. А вот для комбинации 6, 3 получить 2 литра уже не получится. Попробуйте доказать это или опровергнуть самостоятельно.
И не нужно строить никаких гигантских таблиц и конечных автоматов. Яркий пример, когда знания математики программистам нужны.
BubaVV
24.04.2022 11:33Можно решить через треугольную диаграмму. Сумма высот от любой точки треугольника постоянна, все достижимые переливанием состояния лежат на краю диаграммы. Ну и ограничения по объемам легко добавить, срезав вершину
gdt
24.04.2022 13:37Мы в университете решали на прологе/хаскелле через поиск (bfs/dfs) в пространстве состояний - примерно как у вас только таблица переходов нигде не хранится, а переходы из одного состояния в другой задаются как раз допустимыми действиями. Там и литры и волки с козлами и капустой и т д - все решается примерно по одинаковой методике и одинаково легко. Жаль с шахматами такое уже не прокатывает.
vvviperrr
никогда не понимал, как самуэль джексон так быстро ее решил в экстремальной ситуации. я сидел тупил минут 5.
о, превью изменилось. ну теперь мой камент не имеет смысла. спасибо, автор.
REPISOT
Насчет экстремальной ситуации не скажу, но мне понадобилось секунд 15-20. Все дело в опыте. У нас такие задачи в школе постоянно давали. На две емкости, весы и монеты и прочее.
tuxi
Вот вам 2 канистры емкостью 5 и 3 литра, наполненные водой (то есть вода уже в канистрах и больше ее брать негде). Сделайте мне 2 раза по 4 литра)
Казалось бы такая мелочь, а решение уже совсем другое (если вообще есть)
Правильная постановка задачи, уже половина решения.
LuchS-lynx
формально если канистры симметричные, то, канистру наклонить и выливать воду пока она своей поверхностью не "рассечет" канистру по диагонали от одного края на днище до диаметрально противоположного края на верхнем срезе. Вернуть канистру в нормальное положение. то мы получим четко пол канистры. 5/2=2,5л, 3/2=1,5л, 2,5+1,5=4л, но такое решение упирается в симметрию формы
Bronx
Я так полагаю, что есть ещё какая-то пустая безразмерная ёмкость, в которую нужно будет отлить вторые 4 литра? Тогда
где
<...>
— векторы состояния (объём воды в емкостях 1, 2 и 3),и
[x->y]
— переходы "перелить из x в y сколько можно"Пустая ёмкость должна вмещать больше 6 литров (если ровно 6, то решение можно укоротить на один шаг)
Bronx
Но, вообще говоря, это то же самое решение, что и для исходной задачи, просто внешняя среда заменена на специальную ёмкость, и шаги типа "вылить всю воду в окружающее пространство" заменены на "вылить всю воду в ёмкость 3"
Enverest
Превью не изменилось. КПДВ видно в списке статей, а внутри поста картинки нету. Boomburum — это баг или так задумано?
Dolios
Сейчас превью и статья, насколько я знаю, это просто разные тексты. Кто-то там одно и то же размещает, кто-то нет.