Пятница, 29.03.2024, 01:05
Приветствую Вас Гость | RSS
Главная | Каталог статей | Регистрация | Вход

Главная » Статьи » Мои статьи

РЕШЕНИЕ ЗАДАЧИ МАРТИНА ГАРДНЕРА

**********************

РЕШЕНИЕ  ЦЕЛОЧИСЛЕННОЙ  ЗАДАЧИ

 

Для  дальнейшей  иллюстрации возможностей MATLAB рассмотрим целочисленную  задачу,  предложенную американским математиком Мартином  Гарднером:

На  необитаемый  остров попало 5 человек и одна обезьяна .

Весь  день  собирали  они  кокосовые орехи: собрали хорошую  кучу! Ночью  один из  друзей  решил  забрать  свою  долю - разделил  он  орехи  на 5 равных частей, при этом остался  один лишний  кокос - его  он отдал обезьяне,  забрал  свою  часть  кокосов и лег спать. Точно  так же  поступили  и  оставшиеся четверо - каждый  вставал  делил  орехи  на  5  равных частей , у  каждого  оставался  один  орех, который  доставался  обезьяне.

Свою  долю  деливший  забирал  и  ложился спать. На  утро  друзья еще  раз разделили  остаток орехов  на  5 равных  частей, а  вот  обезьяне на утро ореха  не  досталось.

Сколько  всего  было  орехов?

Гарднер не даёт решения, лишь  отмечая, что найти  решение  непросто. На компьютера подобные задачи решаются

в доли  секунды, даже если  использовать обычный  перебор.

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

EXCEL  не увенчалась успехом. Не известно, что за алгоритм

используется для целочисленного решения.

Используя традиционное программирование (написав макрос на VBA) решение было получено моментально, так как

алгоритм решения элементарен. Схема алгоритма приведена

на следующей странице. Далее следует текст макроса. Он приведен для того, чтобы  пояснить маленькую хитрость, примененную в решении. Естественно, что в любом случае число орехов должно быть целым, однако для того чтобы  компьютер

"почувствовал"  наличие остатка при делении на пять число

орехов ( переменные KOKOS) объявлены как действительные  числа. Для "обнаружения"  остатка использованы функции

VBA INT и FIX.

Текст макроса VBA

Private Sub Command1_Click()

Dim KOKOS As Double, KI As Integer

Dim KOKOS1 As Double, KF As Integer

Dim KOKOS2 As Double, KOKOS3 As Double, KOKOS4 As Double, KOKOS5 As Double

Rem  ПРОИЗВОЛЬНОЕ НАЧАЛЬНОЕ ЧИСЛО СОБРАННЫХ  КОКОСОВ

KOKOS = 10#

Rem  ОПЕРАТОР  С  МЕТКОЙ 5 БУДЕТ УВЕЛИЧИВАТЬ  ЧИСЛО  КОКОСОВ СОГЛАСНО УСЛОВИЯМ

5 KOKOS = KOKOS + 1#

Rem ================================

Rem   ДЕЛИТ  ПЕРВЫЙ  УЧАСТНИК

Rem==================================

KI = Int(-(KOKOS - 1) / 5) 'полученое с дробным остатком число округляется до меньшего целого================================================================

KF = Fix(-(KOKOS - 1) / 5) 'полученое с дробным остатком число округляется до большего целого================================================================

If Abs(KI) - Abs(KF) <> 0 Then GoTo 5 ' если деление на 5 имеет остаток уходим на увеличение числа !======================================================

If Abs(KI) - Abs(KF) = 0 Then KOKOS1 = KOKOS - (KOKOS - 1) / 5 - 1 ' осталось после первого

ZABRAL1 = (KOKOS - 1) / 5

Rem  следующие  четыре блока аналогичны  первому===========================

KI = Int(-(KOKOS1 - 1) / 5)

KF = Fix(-(KOKOS1 - 1) / 5)

If Abs(KI) - Abs(KF) <> 0 Then GoTo 5

If Abs(KI) - Abs(KF) = 0 Then KOKOS2 = KOKOS1 - (KOKOS1 - 1) / 5 - 1

ZABRAL2 = (KOKOS1 - 1) / 5

Rem   ДЕЛИТ   ТРЕТИЙ УЧАСТНИК=========================================

KI = Int(-(KOKOS2 - 1) / 5)

KF = Fix(-(KOKOS2 - 1) / 5)

If Abs(KI) - Abs(KF) <> 0 Then GoTo 5

If Abs(KI) - Abs(KF) = 0 Then KOKOS3 = KOKOS2 - (KOKOS2 - 1) / 5 - 1

ZABRAL3 = (KOKOS2 - 1) / 5

Rem   ДЕЛИТ   ЧЕТВЕРТЫЙ УЧАСТНИК===================================

KI = Int(-(KOKOS3 - 1) / 5)

KF = Fix(-(KOKOS3 - 1) / 5)

If Abs(KI) - Abs(KF) <> 0 Then GoTo 5

If Abs(KI) - Abs(KF) = 0 Then KOKOS4 = KOKOS3 - (KOKOS3 - 1) / 5 - 1

ZABRAL4 = (KOKOS3 - 1) / 5

Rem   ДЕЛИТ  ПЯТЫЙ  УЧАСТНИК========================================

KI = Int(-(KOKOS4 - 1) / 5)

KF = Fix(-(KOKOS4 - 1) / 5)

If Abs(KI) - Abs(KF) <> 0 Then GoTo 5

If Abs(KI) - Abs(KF) = 0 Then KOKOS5 = KOKOS4 - (KOKOS4 - 1) / 5 - 1

ZABRAL5 = (KOKOS4 - 1) / 5

Rem   ВЫВОД  РЕЗУЛЬТАТОВ НА ЭКРАН В РАБОЧИЙ ЛИСТ EXCEL   ============

Range("D6").Value = KOKOS

Range("D7").Value = ZABRAL1

Range("D8").Value = ZABRAL2

Range("D9").Value = ZABRAL3

Range("D10").Value = ZABRAL4

Range("D11").Value = ZABRAL5

Rem  ПОСЛЕДНИЙ УТРЕННИЙ  ДЕЛЕЖ

NA_UTRO = (KOKOS - ZABRAL1 - ZABRAL2 - ZABRAL3 - ZABRAL4 - ZABRAL5 - 5) / 5

Rem Print " А  ПО УТРУ  КАЖДЫЙ  ПОЛУЧИЛ ЕЩЁ"

Range("D13").Value = NA_UTRO          End Sub

 

 Tрадиционное  программирование требует некоторых затрат времени на написание и отладку макроса( естественно, если Вы владеете VBA). С помощью написанного макроса

задача была решена моментально. Экран EXCEL с решением

представлен на следующем рисунке.

 


Получено решение – было собрано - 3121 кокос, забирались

кокосы в следующем порядке-624,499,399,319 и 255.

Желающие могут проверить решение с помощью калькулятора.

Применяя MATLAB  можно решать подобные  задачи

несколько проще, а самое главное, нагляднее.
 
ПОСМОТРЕТЬ РЕШЕНИЕ МОЖНО ЕСЛИ
 
ЕСТЕСТВЕННО , ЗАПУСКАТЬ ПРОГРАММУ В УСТАНОВЛЕННОМ НА ВАШ ПК
MATLAB
  
Категория: Мои статьи | Добавил: BN (26.06.2008) | Автор: BN
Просмотров: 4977