Что такое декларативное программирование?
Я продолжаю слышать этот термин, затронутый в нескольких разных контекстах. Что это?
Ответы
Ответ 1
Декларативное программирование - это когда вы пишете свой код таким образом, чтобы он описывал, что вы хотите делать, а не как вы хотите это сделать. Остается до компилятора выяснить, как это сделать.
Примерами декларативных языков программирования являются SQL и Prolog.
Ответ 2
Другие ответы уже выполняют фантастическую работу, объясняя, что такое декларативное программирование, поэтому я просто приведу несколько примеров того, почему это может быть полезно.
Контекстная независимость
Декларативные программы не зависят от контекста. Поскольку они только заявляют, какова конечная цель, но не являются промежуточными шагами для достижения этой цели, одна и та же программа может использоваться в разных контекстах. Это трудно сделать с императивными программами, потому что они часто зависят от контекста (например, скрытого состояния).
В качестве примера возьмем yacc
. Это генератор парсеров. компилятор компилятора, внешний декларативный DSL для описания грамматики языка, так что парсер для этого языка может автоматически генерироваться из описания. Из-за своей контекстной независимости вы можете делать много разных вещей с такой грамматикой:
- Сгенерируйте C-парсер для этой грамматики (исходный вариант использования для
yacc
)
- Сгенерировать парсер С++ для этой грамматики
- Создайте парсер Java для этой грамматики (используя Jay)
- Сгенерировать парсер С# для этой грамматики (используя GPPG)
- Создайте парсер Ruby для этой грамматики (используя Racc)
- Создайте визуализацию дерева для этой грамматики (используя GraphViz)
- просто сделайте красивую печать, причудливое форматирование и синтаксическую подсветку самого исходного файла yacc и включите его в свое справочное руководство в качестве синтаксической спецификации вашего языка.
И еще много & hellip;
Оптимизация
Поскольку вы не определяете компьютер, какие шаги следует предпринять и в каком порядке, он может более свободно изменять вашу программу, возможно, даже выполнять некоторые задачи параллельно. Хорошим примером является планировщик запросов и оптимизатор запросов для базы данных SQL. Большинство баз данных SQL позволяют отображать запрос, который они фактически выполняют, и запрос, который вы попросили выполнить. Часто эти запросы не похожи друг на друга. Планировщик запросов учитывает то, о чем вы даже не мечтали: вращательная латентность дискового диска, например, или тот факт, что какое-то совершенно другое приложение для совершенно другого пользователя просто выполнило аналогичный запрос и таблицу, в которой вы находитесь присоединение с вами и что вы так много работали, чтобы избежать загрузки, все равно уже в памяти.
Здесь есть интересный компромисс: машине приходится больше работать, чтобы понять, как сделать что-то, чем это было бы на императивном языке, но когда он это выяснит, у него гораздо больше свободы и гораздо больше информации для этапа оптимизации.
Ответ 3
Прошу прощения, но я должен не согласиться со многими другими ответами. Я хотел бы остановить это запутанное непонимание определения декларативного программирования.
Определение
Ссылочная прозрачность (RT) подвыражений является единственным обязательным атрибутом выражения декларативного программирования, поскольку это единственный атрибут, который не разделяется с императивными программирование.
Другие цитируемые атрибуты декларативного программирования, вытекающие из этого RT. Пожалуйста, нажмите гиперссылку выше для подробного объяснения.
Пример таблицы
В двух ответах говорится о программировании электронных таблиц. В тех случаях, когда программирование таблиц (формулы a.k.a.) не имеет доступа к изменяемому глобальному состоянию, тогда оно декларирует программирование. Это связано с тем, что изменчивыми значениями ячеек являются монолитный ввод и вывод "main()" (вся программа). Новые значения не записываются в ячейки после выполнения каждой формулы, поэтому они не изменяются для жизни декларативной программы (выполнение всех формул в электронной таблице). Таким образом, по отношению друг к другу формулы рассматривают эти изменчивые ячейки как неизменные. Функция RT разрешает доступ к неизменяемому глобальному состоянию (а также изменяемое локальное состояние).
Таким образом, способность мутировать значения в ячейках, когда программа завершается (как результат из "main()" ), не делает их изменяемыми хранимыми значениями в контексте правил. Основное различие заключается в том, что значения ячеек не обновляются после выполнения каждой формулы электронной таблицы, поэтому порядок выполнения формул не имеет значения. Значения ячеек обновляются после того, как все декларативные формулы были выполнены.
Ответ 4
затягивая:
Декларативное программирование имеет тенденцию к: -
- Устанавливает декларации или декларативные утверждения, каждый из которых имеет смысл (часто в проблемной области) и может пониматься независимо и изолированно.
Императивное программирование имеет тенденцию к: -
- Последовательности команд, каждая из которых выполняет какое-либо действие; но который может иметь или не иметь смысла в проблемной области.
В результате императивный стиль помогает читателю понять механику, что на самом деле делает система, но может дать мало понимания проблемы, которую она предназначена для решения. С другой стороны, декларативный стиль помогает читателю понять проблемную область и подход, который система принимает к решению проблемы, но менее информативна по вопросу о механизме.
Реальные программы (даже те, которые написаны на языках, которые поддерживают концы спектра, такие как ProLog или C), как правило, имеют разные стили в разных степенях в разных точках, чтобы удовлетворить различные сложности и коммуникационные потребности пьесы. Один стиль не превосходит другого; они просто служат различным целям, и, как и во многих вещах в жизни, умеренность является ключевой.
Ответ 5
Декларативное программирование - это изображение, где императивное программирование - это инструкции для рисования этого изображения.
Вы пишете декларативный стиль, если вы "Рассказываете, что это такое", вместо того, чтобы описывать шаги, которые должен предпринять компьютер, чтобы добраться туда, где вы хотите.
Когда вы используете XML для разметки данных, вы используете декларативное программирование, потому что вы говорите: "Это человек, день рождения, а также есть уличный адрес".
Некоторые примеры того, где декларативное и императивное программирование объединяются для большего эффекта:
-
Windows Presentation Foundation использует декларативный синтаксис XML для описания того, как выглядит пользовательский интерфейс, и что отношения (привязки) находятся между элементами управления и базовыми структурами данных.
-
Структурированные файлы конфигурации используют декларативный синтаксис (так же просто, как пары "ключ = значение" ), чтобы определить, что означает строка или значение данных.
-
HTML помещает текст с тегами, которые описывают, какую роль имеет каждая часть текста относительно всего документа.
Ответ 6
Представьте себе страницу excel. С столбцами, заполненными формулами для расчета налоговой декларации.
Вся логика объявляется в ячейках, порядок вычисления определяется самим формулой, а не процедурной.
Вот что такое декларативное программирование. Вы объявляете проблемное пространство и решение, а не поток программы.
Пролог - единственный декларативный язык, который я использую. Это требует иного типа мышления, но хорошо учиться, если просто подвергать вас чему-то, кроме типичного процедурного языка программирования.
Ответ 7
Поскольку я написал свой предыдущий ответ, я сформулировал новое определение декларативного свойства, которое приведено ниже. Я также определил императивное программирование как двойное свойство.
Это определение превосходит то, которое я представил в моем предыдущем ответе, потому что оно кратким и более общим. Но это может быть труднее заглянуть, потому что имплементация теорем о неполноте, применимых к программированию и жизни в целом, людям трудно обдумать.
В цитируемом объяснении определения обсуждается роль, которую играет чисто функциональное программирование в декларативном программировании.
Декларативный и императивный
Декларативное свойство является странным, тупым и трудным для захвата в технически точном определении, которое остается общим, а не двусмысленным, потому что это наивное представление о том, что мы можем объявить значение (ака семантики) программы без возникновения непреднамеренной стороны последствия. Существует неотъемлемая напряженность между выражением смысла и избеганием непреднамеренных эффектов, и это напряжение на самом деле происходит от теорем неполноты программирования и нашей вселенной.
Это упрощение, технически неточное и часто двусмысленное, чтобы определить декларативное как " что делать " и необходимо как " как do ". Двусмысленным случаем является" что "- это" как "в программе, которая выводит программу - компилятор.
Очевидно, что неограниченная рекурсия которая делает язык Turing завершен, также аналогична семантике - не только в синтаксической структуре оценки (оперативная семантика a.k.a.). Это логически является примером, аналогичным теореме Гёделя -" любая полная система аксиом также противоречива ". Подумайте о противоречивой странности этой цитаты! Это также пример, демонстрирующий, как выражение семантики не имеет доказуемой границы, поэтому мы не можем доказать 2, что программа (и аналогично ее семантика) останавливается на теореме Хэллинга.
Теоремы о неполноте вытекают из фундаментальной природы нашей Вселенной, которая, как указано во втором Законе Термодинамики, заключается в том, что "энтропия (a.k.a. # независимых возможностей) навсегда стремится к максимуму ". Кодирование и дизайн программы никогда не заканчиваются - она жива! - потому что она пытается удовлетворить потребность в реальном мире, а семантика реального мира всегда меняется и имеет тенденцию к большему количеству возможностей. Люди никогда не перестают открывать новые вещи (включая ошибки в программах;).
Чтобы точно и технически захватить это вышеупомянутое желаемое понятие в этой странной вселенной, у которой нет края (задумайтесь над тем, что" нет "снаружи нашей вселенной), требует краткого, но обманчиво-непростого определения, которое будет звучать некорректно до тех пор, пока это объясняется глубоко.
Определение:
В декларативном свойстве может быть только один возможный набор операторов, который может выражать каждую конкретную модульную семантику.
Обязательным свойством 3 является двойственное, где семантика несовместима по составу и/или может быть выражена вариациями наборов операторов.
Это определение декларативного является явно локальным в семантической области, что означает, что он требует, чтобы модульная семантика сохраняла свое последовательное значение независимо от того, где и как оно создавалось и использовалось в глобальном масштабе. Таким образом, каждая декларативная модульная семантика должна быть внутренне ортогональна всем возможным другим, а не невозможным (из-за теорем неполноты) глобальному алгоритму или модели для подтверждения согласованности, которая также является точкой" Больше не всегда лучше" Роберта Харпера, профессора компьютерных наук в Университете Карнеги Меллона, одного из разработчиков Standard ML.
Примеры этой модульной декларативной семантики включают функторы теории категорий, например. Applicative
, номинальная типизация, пространства имен, именованные поля и w.r.t. к оперативному уровню семантики, тогда чисто функциональное программирование.
Таким образом, хорошо разработанные декларативные языки могут более четко выражать смысл, хотя и с некоторой потерей общности в том, что может быть выражено, но в что может быть выражено с внутренней консистенцией.
Примером вышеупомянутого определения является набор формул в ячейках программы электронных таблиц, которые, как ожидается, не будут давать то же значение при перемещении в разные ячейки столбцов и строк, т.е. изменятся идентификаторы ячеек. Идентификаторы ячеек являются частью и не являются излишними для предполагаемого значения. Таким образом, результат каждой таблицы уникален w.r.t. к идентификаторам ячеек в наборе формул. Согласованная модульная семантика в этом случае - это использование идентификаторов ячеек в качестве входных и выходных данных чистых функций для формул ячеек (см. Ниже).
Язык гипертекстовой маркировки, ака HTML - язык для статических веб-страниц - является примером высоко (но не идеально 3) декларативного языка, который (при не ранее, чем HTML 5) не имел возможности выражать динамическое поведение. HTML - это, пожалуй, самый простой язык для изучения. Для динамического поведения обязательный скриптовый язык, такой как JavaScript, обычно сочетается с HTML. HTML без JavaScript подходит для декларативного определения, потому что каждый номинальный тип (т.е. Теги) сохраняет свое согласованное значение под композицией в рамках правил синтаксиса.
Конкурирующим определением для декларативного является commutative и idempotent свойств семантических операторов, т.е. что операторы могут быть переупорядочены и дублированы без изменения значения. Например, операторы, присваивающие значения именованным полям, могут быть переупорядочены и дублированы без изменения значения программы, если эти имена являются модульными w.r.t. к любому подразумеваемому порядку. Имена иногда подразумевают порядок, например. Идентификаторы ячеек включают в себя их столбцы и позицию в строке - перемещение итоговой таблицы в таблицу изменяет ее значение. В противном случае эти свойства неявно требуют глобальной согласованности семантики. Как правило, невозможно создать семантику операторов, чтобы они оставались согласованными, если они были упорядочены произвольно или дублировались, потому что порядок и дублирование являются неотъемлемой частью семантики. Например, утверждения "Foo exists" (или конструкция) и "Foo не существует" (и уничтожение). Если рассматривать случайную несогласованность в эндемике предполагаемой семантики, то можно принять это определение как достаточно общее для декларативного свойства. По существу это определение пустое как обобщенное определение, поскольку оно пытается сделать согласованность ортогональной семантике, т.е. Игнорировать тот факт, что семантика вселенной динамически неограничена и не может быть захвачена в глобальной парадигме когерентности.
Требование коммутативных и идемпотентных свойств для (порядка структурной оценки) оперативной семантики нижнего уровня преобразует оперативную семантику в декларативную локализованную модульную семантику, например. чистое функциональное программирование (включая рекурсию вместо императивных циклов). Тогда рабочий порядок деталей реализации не влияет (т.е. Глобально распространяется) на согласованность семантики более высокого уровня. Например, порядок оценки (и, теоретически, дублирования) формул электронных таблиц не имеет значения, поскольку выходы не копируются на входы до тех пор, пока не будут вычислены все выходы, то есть аналогичны чистым функциям.
C, Java, С++, С#, PHP и JavaScript не являются особенно декларативными. Синтаксис синтаксиса и синтаксиса Python более декларативно связанный с предполагаемые результаты, т.е. последовательная синтаксическая семантика, которая устраняет посторонние, поэтому можно легко понять код после того, как они его забыли. Copute и Haskell обеспечивают соблюдение детерминизм оперативной семантики и поощрение "не повторять себя "(DRY), потому что они допускают чисто функциональную парадигму.
2 Даже там, где мы можем доказать семантику программы, например. с языком Coq, это ограничивается семантикой, выраженной в типизации, и типизация никогда не может захватить всю семантику программы - даже для языков, которые не являются Тьюрингом, например, с HTML + CSS можно выразить несогласованные комбинации, которые, таким образом, имеют семантику undefined.
3 Многие объяснения неправильно утверждают, что только императивное программирование имеет синтаксически упорядоченные утверждения. Я разъяснил эту путаницу между императивным и функциональным программированием. Например, порядок выражений HTML не уменьшает согласованность их значения.
Изменить: я отправил следующий комментарий в блог Роберта Харпера:
в функциональном программировании... диапазон изменения переменной - это тип
В зависимости от того, как можно отличить функциональность от императивного программирования, ваш "назначаемый в императивной программе" также может иметь тип, устанавливающий привязку к его изменчивости.
Единственное не-запутанное определение, которое я в настоящее время ценю для функционального программирование является а) функционирует как первоклассные объекты и типы, б) предпочтение для рекурсии над циклами и/или в) чистые функции, т.е. те функции, которые не влияют на желаемую семантику программа, когда memoized ( таким образом, совершенно чистый функциональный программирования не существует в общей смысловой семантике из-за воздействия эксплуатационной семантики, например. Память распределениесуб > ).
Идемпотентное свойство чистой функции означает вызов функции на его переменные могут быть заменены его значением, которое обычно не является случай аргументов императивной процедуры. Чистые функции кажутся декларативными w.r.t. к несохраненным переходам состояний между входами и типами результатов.
Но состав чистых функций не поддерживает таких согласованность, поскольку можно моделировать побочный эффект (глобальный state) императивный процесс на чистом функциональном языке программирования, например Haskell IOMonad и, кроме того, полностью невозможно не допускайте таких действий в любом полном функциональном программировании Тьюринга язык.
Как я писал в 2012 году, что похоже на аналогичный консенсус комментарии в ваш недавний блог, что декларативное программирование - это попытка захватить представление о том, что предполагаемая семантика никогда непрозрачный. Примерами непрозрачной семантики являются зависимость от порядка, зависимость от стирания семантики более высокого уровня при операционном семантический слой (например, отбрасывает не конверсии и не генерирует обобщенные данные ограничить семантику более высокого уровня) и зависимость от переменных значений который не может быть проверен (подтвержден правильным) языком программирования.
Таким образом, я пришел к выводу, что только полные языки, не содержащие Тьюринга, могут быть декларативной.
Таким образом, один однозначный и четкий атрибут декларативного языка может заключаться в том, что его выход может быть доказан, чтобы подчиняться некоторому перечислимому набору порождающие правила. Например, для любой конкретной программы HTML (игнорируя различия в том, как интерпретаторы расходятся), который не является сценарием (т.е. не является полным Тьюринга), то его выходная изменчивость может быть перечислим. Или более кратко HTML-программа - это чистая функция его изменчивость. Кроме того, программа электронных таблиц является чистой функцией ее входные переменные.
Итак, мне кажется, что декларативные языки являются антитезой неограниченная рекурсия, т.е. вторая неполная Gödel теорема самореференциальных теорем не может быть доказана.
Леси Лэмпорт написал сказку о том, как Евклид мог бы работал над теоремами неполноты Гёделя, применимыми к математическим доказательствам в контексте языка программирования путем сопоставления между типами и логика (соответствие Карри-Говарда и т.д.).
Ответ 8
Это метод программирования, основанный на описании того, что что-то должно делать или быть вместо того, чтобы описывать, как он должен работать.
Другими словами, вы не пишете алгоритмы из выражений, вы просто планируете, как вы хотите, чтобы что-то было. Два хороших примера - HTML и WPF.
Эта статья в Википедии - хороший обзор: http://en.wikipedia.org/wiki/Declarative_programming
Ответ 9
Я уточнил свое понимание декларативного программирования, начиная с декабря 2011 года, когда я представил ответ на этот вопрос. Здесь следует мое нынешнее понимание.
Длинная версия моего понимания (исследования) подробно описана в эта ссылка, которую вы должны прочитать получить глубокое понимание резюме, которое я приведу ниже.
Императивное программирование - это где изменяемое состояние сохраняется и считывается, поэтому упорядочение и/или дублирование программных команд могут изменять поведение (семантику) программы (и даже вызывать ошибку, то есть непреднамеренное поведение).
В самом наивном и крайнем смысле (который я утверждал в своем предыдущем ответе) декларативное программирование (DP) избегает всех сохраненных изменчивых состояний, поэтому упорядочение и/или дублирование инструкций программы могут NOT изменить поведение (семантику) программы.
Однако такое экстремальное определение не будет очень полезно в реальном мире, поскольку почти каждая программа включает сохраненное изменчивое состояние. Пример таблицы электронных таблиц соответствует этому крайнему определению DP, поскольку весь программный код запускается до завершения с помощью одной статической копии входного состояния до того, как будут сохранены новые состояния. Затем, если какое-либо состояние изменено, это повторяется. Но большинство программ реального мира не могут быть ограничены такой монолитной моделью изменений состояния.
Более полезное определение DP заключается в том, что упорядочение и/или дублирование инструкций программирования не изменяют никакой непрозрачной семантики. Другими словами, не существует скрытых случайных изменений в семантике - любые изменения в порядке команд программы и/или дублировании вызывают только намеченные и прозрачные изменения в поведении программы.
Следующим шагом будет разговор о том, какие модели программирования или парадигмы помогают в DP, но здесь не вопрос.
Ответ 10
Декларативное программирование - это программирование с декларациями, т.е. декларативными предложениями. Декларативные предложения имеют ряд свойств, которые отличают их от императивных предложений. В частности, объявления:
- коммутативный (может быть переупорядочен)
- ассоциативный (может быть перегруппирован)
- idempotent (может повторяться без изменения смысла)
- monotonic (объявления не вычитают информацию)
Важным моментом является то, что все это структурные свойства и ортогональны предмету. Декларативное не относится к "Что против того, как". Мы можем объявить (представлять и сдерживать) "как" так же легко, как мы объявляем "что". Декларативный - это структура, а не контент. Декларативное программирование оказывает существенное влияние на то, как мы абстрактно и реорганизуем наш код, и как мы его модулируем в подпрограммах, но не столько на модели домена.
Часто мы можем конвертировать из императива в декларативный, добавляя контекст. Например. от "Поверните налево. (... подождите...) Поверните направо." Боб повернет налево на перекрестке Foo и Bar в 11:01. Боб повернуть направо на перекрестке Бар и Баз в 11:06". Обратите внимание, что в последнем случае предложения являются идемпотентными и коммутативными, тогда как в первом случае переупорядочение или повторение предложений сильно изменят значение программы.
Что касается монотонности, объявления могут добавлять ограничения, которые вычитают возможности. Но ограничения все еще добавляют информацию (точнее, ограничения - это информация). Если нам нужны изменяющиеся во времени декларации, типично моделировать это с явной временной семантикой - например. от "шара плоский" до "мяч плоский в момент времени Т". Если у нас есть две противоречивые декларации, мы имеем несогласованную декларативную систему, хотя это может быть разрешено путем введения мягких ограничений (приоритеты, вероятности и т.д.) Или использования парасодержащей логики.
Ответ 11
Вот пример.
В CSS (используется для стилизации HTML-страниц), если вы хотите, чтобы элемент изображения имел 100 пикселей в высоту и 100 пикселей в ширину, вы просто "объявляете" то, что хотите:
#myImageId {
height: 100px;
width: 100px;
}
Вы можете рассматривать CSS декларативный язык "таблицы стилей".
Механизм браузера, который читает и интерпретирует этот CSS, может сделать изображение таким высоким и таким широким, как бы оно ни желало. Различные браузерные механизмы (например, движок IE, движок для Chrome) будут выполнять эту задачу по-разному.
Их уникальные реализации, конечно, НЕ написаны на декларативном языке, а в процедурной форме, например Assembly, C, С++, Java, JavaScript или Python. Этот код представляет собой последовательность шагов, которые необходимо выполнить шаг за шагом (и может включать вызовы функций). Он может делать такие вещи, как интерполировать значения пикселей и отображать на экране.
Ответ 12
Описание компьютера, что вы хотите, а не как что-то сделать.
Ответ 13
Это может показаться странным, но я бы добавил Excel (или любую электронную таблицу) в список декларативных систем. Хорошим примером этого является здесь.
Ответ 14
Я бы объяснил это как DP - способ выразить
- Выражение цели, условия для - того, что мы ищем. Есть один, может быть или много?
- Некоторые известные факты
- Правила, которые расширяют информацию о знании
... и где есть двигатель вычитания, который обычно работает с алгоритмом унификации, чтобы найти цели.
Ответ 15
Декларативное программирование - это "процесс программирования на языках, которые соответствуют ментальной модели разработчика, а не операционной модели машины".
Разница между декларативным и императивным программированием хорошо
иллюстрируется проблемой анализа структурированных данных.
Обязательная программа будет использовать взаимно рекурсивные функции для потребления входных данных
и генерировать данные. В декларативной программе будет выражена грамматика, определяющая
структуру данных, чтобы затем можно было проанализировать.
Разница между этими двумя подходами заключается в том, что декларативная программа
создает новый язык, который более точно сопоставляется с ментальной моделью
проблема, чем его язык-хозяин.
Ответ 16
Насколько я могу судить, он начал использоваться для описания систем программирования, таких как Prolog, потому что пролог (предположительно) об объявлении вещей абстрактным образом.
Это все больше означает очень мало, поскольку оно имеет определение, данное выше. Должно быть ясно, что между декларативным программированием Haskell существует пропасть, в отличие от декларативного программирования HTML.
Ответ 17
Еще несколько примеров декларативного программирования:
- Разметка ASP.Net для привязки данных. Он просто говорит: "Заполните эту сетку этим источником", например, и оставит ее в системе, как это происходит.
- выражения Linq
Декларативное программирование хорошо, потому что оно может помочь упростить вашу ментальную модель * кода и потому, что в конечном итоге это может быть более масштабируемым.
Например, скажем, у вас есть функция, которая делает что-то для каждого элемента в массиве или списке. Традиционный код будет выглядеть так:
foreach (object item in MyList)
{
DoSomething(item);
}
Там нет большой сделки. Но что, если вы используете более-декларативный синтаксис и вместо этого определяете DoSomething() как действие? Тогда вы можете сказать так:
MyList.ForEach(DoSometing);
Это, конечно, более кратким. Но я уверен, что у вас больше проблем, чем просто сохранение двух строк кода здесь и там. Производительность, например. Старый способ, обработка должна была быть выполнена последовательно. Что, если метод .ForEach() дал вам возможность сообщить, что он может обрабатывать обработку параллельно, автоматически? Теперь вы внезапно сделали свой код многопоточным очень безопасным способом и только изменили одну строку кода. И, фактически, есть расширение для .Net, которое позволяет вам сделать именно это.
- Если вы следуете этой ссылке, она приведет вас к сообщению в блоге моим другом. Весь пост немного длинный, но вы можете прокрутить вниз до заголовка под названием "Проблема" _ и забрать его там без проблем. *
Ответ 18
Это зависит от того, как вы отправляете ответ на текст. В целом вы можете посмотреть программу на определенном виде, но это зависит от того, на какой угол вы смотрите на проблему. Я начну с программы:
Dim Bus, Car, Time, Height As Integr
Опять же, это зависит от того, что проблема в целом. Возможно, вам придется сократить его из-за программы. Надеюсь, что это поможет и потребует обратной связи, если это не так.
Спасибо.