Author Topic: Определить переменную с наименьшим значением в Алгоритме A*.  (Read 6974 times)

0 Members and 1 Guest are viewing this topic.

NStra

  • Освоившийся
  • **
  • Posts: 45
  • Подпись под аватаром.
    • View Profile
Дано:    4 переменных, содержащих произвольные числа.
             Переменные могут быть равными по значению.

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

P.S.       Прошу прощения, если задача окажется легкой...
« Last Edit: April 13, 2015, 02:16:02 PM by NStra »
Тут должна быть подпись...

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Если без рандома, а первая попавшееся
Code: (clickermann) [Select]
$v1 = 300
$v2 = 400
$v3 = 100
$v4 = 200

$min = $v1
IF($v2 < $min)
   $min =  $v2
END_IF
IF($v3 < $min)
   $min =  $v3
END_IF
IF($v4 < $min)
   $min =  $v4
END_IF

              Если таких переменных несколько, выбрать рандомом любую из них.

И что значит выбрать любую из них рандомом? Нужно знать какие именно это переменные?
Потому как выбирать рандомом значения не имеет смысла, они одинаковые.
« Last Edit: April 01, 2015, 04:16:43 PM by Vint »


NStra

  • Освоившийся
  • **
  • Posts: 45
  • Подпись под аватаром.
    • View Profile
Немного не то...
1. Нужно определить переменную, которая содержит минимальное число, а не ее значение.
2. Рандом обязателен, в случае, если минимальных переменных несколько...
Тут должна быть подпись...

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Что-то это мне напоминает... Год назад вот так же пытали про три наименьших из n и требовали именно переменную.

Подход к реализации неправильный. Такие вопросы не должны возникать.
Ну вот ладно, определю я что наименьшее значение находится в переменной $v3. И что я буду с этим делать?
Запомню имя в другой переменной как "$v3"? И как потом это можно использовать?

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


NStra

  • Освоившийся
  • **
  • Posts: 45
  • Подпись под аватаром.
    • View Profile
Да, это похоже работа со строками, возможно и с массивами...+ наверно нагромождение условий...
Пример работы программы:
Вход:
$Dir1=1
$Dir2=1
$Dir3=3
$Dir4=4
Выход:
Print("выбрано $Dir1")
или
Print("выбрано $Dir2")
Тут должна быть подпись...

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Code: (clickermann) [Select]
$Dir1=1
$Dir2=1
$Dir3=3
$Dir4=4

$min = $Dir1
IF($Dir2 < $min)
   $min =  $Dir2
END_IF
IF($Dir3 < $min)
   $min =  $Dir3
END_IF
IF($Dir4 < $min)
   $min =  $Dir4
END_IF

IF($Dir1 = $min)
   ARRPUSH($names, "$Dir1")
END_IF
IF($Dir2 = $min)
   ARRPUSH($names, "$Dir2")
END_IF
IF($Dir3 = $min)
   ARRPUSH($names, "$Dir3")
END_IF
IF($Dir4 = $min)
   ARRPUSH($names, "$Dir4")
END_IF

$name = $names[RND(0,ARRSIZE($names)-1)]

Print("выбрано ", $name)

И всё равно это неверный подход. Если есть несколько однотипных переменных, лучше хранить их в массиве, а индекс массива как раз и будет индикатором какая это из переменных.

А то при любых подобных обработках невозможно применить циклы и приходится кучу кода писать и дублировать вручную.
$Dir[0.....]


Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Мой вариант, номер определяет но с рандомом нужно думать..

Code: (clickermann) [Select]
$c1=4000
$c2=2
$c3=2
$c4=9

STRSEPARATE(STRCONCAT($c1,":",$c2,":",$c3,":",$c4), ":", $analiz)

$num=9999999

FOR($a=0,$a<ARRSIZE($analiz))
   $min = $analiz[$a]
   IF($min < $num)
      $c = $a+1
      $num = $min
   END_IF
END_CYC

LOGWRITE ("Номер = ",$c," Min = ",$num)
HALT

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Ну вот через массивы.
Code: (clickermann) [Select]
$Dir1 = 1
$Dir2 = 1
$Dir3 = 3
$Dir4 = 4

STRSEPARATE(STRCONCAT($Dir1,":",$Dir2,":",$Dir3,":",$Dir4), ":", $analiz)

$min = 99999999999
FOR($a=0,$a < ARRSIZE($analiz))
   IF($analiz[$a] < $min)
      $min = $analiz[$a]
   END_IF
END_CYC

FOR($a=0,$a < ARRSIZE($analiz))
   IF($analiz[$a] = $min)
      ARRPUSH($names, $a)
   END_IF
END_CYC

$name = $names[RND(0,ARRSIZE($names)-1)]

Print("выбрано $Dir", $name+1)

HALT


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Вот так даже красивее
Code: (clickermann) [Select]
$Dir1 = 1
$Dir2 = 1
$Dir3 = 3
$Dir4 = 4

STRSEPARATE(STRCONCAT($Dir1,":",$Dir2,":",$Dir3,":",$Dir4), ":", $analiz)

$min = 99999999999
FOR($a=0,$a < ARRSIZE($analiz))
   IF($analiz[$a] < $min)
      $min = $analiz[$a]
      UNDEFINE($names)
      ARRPUSH($names, $a)
   ELSE
      IF($analiz[$a] = $min)
         ARRPUSH($names, $a)
      END_IF
   END_IF
END_CYC

$name = $names[RND(0,ARRSIZE($names)-1)]
Print("выбрано $Dir", $name+1)

HALT


NStra

  • Освоившийся
  • **
  • Posts: 45
  • Подпись под аватаром.
    • View Profile
Эта задача: кусок алгоритма A* http://www.policyalmanac.org/games/aStarTutorial_rus.htm
В данном случае 4-и переменных это значения H где:
$Dir1 - влево
$Dir2 - вверх
$Dir3 - вправо
$Dir4 - вниз
...
Задумка вот в чем:
Если кликер будет обходить один и тот же путь с рандомом, то в 50% случаев он выберет короткий, в остальных пойдет по длинному (например стена влево больше чем вправо).

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

В идеале я хочу сделать вот что:
Кликер должен не выбирать пути, а мысленно пройти оба и сравнить длину, после выбрать короткий путь.
Тут должна быть подпись...

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Там сам бог велел массив использовать. А индексы как раз и будут обозначать направление.
0 - влево, 1 - вверх ... и т.д.

Только рандом там не нужен, ты неправильно понял. Мы должны брать минимальное, но не важно какое. Как раз пока стоимость не начнет уменьшатся мы будем по очереди проверять то с одной стороны стены, то с другой.
И если стоимость новой открытой клетки равна, то мы должны следующей проверять её. (этот момент в статье упущен)
Если начнёт уменьшаться, вторая ветвь отвалится сама собой.
И не нужно  гадать 50/50

Кликер должен не выбирать пути, а мысленно пройти оба и сравнить длину, после выбрать короткий путь.
А если их будет не два, а 5 или 10 или 100? Алгоритм поиска пути как раз и позволяет не обходить их все. Иначе ресурсов и времени потребуется уйма


Ха!  :D А я после того как дал ссылку, почти каждый день думаю об этом A*
Хочется реализовать, но самому лень начинать, т.к. нет практической задачи, только спортивный интерес.
Я уже думал клич кинуть на форум с кем скооперироваться для совместного создания. Всё ж веселее. Но так и не решился, подумал кому оно надо.

Я представляю себе, что если поле большое, реализация на кликере может быть медленная. Не знаю на сколько, правда.
Но уже подумывал и о питоне и о AutoIT. Можно там модуль сделать трудоёмкий.

И самое главное, я не знаю какой выбрать способ хранения начальных данных, чтобы была универсальность и скрипт можно было использовать и в других задачах.
« Last Edit: April 01, 2015, 05:34:42 PM by Vint »


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Там кстати в конце есть ссылка на код на C++
Я язык не знаю, но там есть скомпилированный код. Очень забавно погонять его.
Там два: редактор с показом всех построений-вычислений
и большой лабиринт/редактор кде бегают чудики и как они хорошо находят путь.


NStra

  • Освоившийся
  • **
  • Posts: 45
  • Подпись под аватаром.
    • View Profile
Доброго времени суток.
Решил достать из долгого ящика скрипт поиска пути.
Оказалось, что мой код содержит ошибки...Которые я еще и не могу исправить. :'(
После запуска, переменные Dir работают странно...Определяют стены там, где их нет, и наоборот.
Либо вообще определяют, что стены везде...
Карту и идентификаторы в файлах я проверял, там ошибок нет.
Code: [Select]
#name "ALGORITM A"
// В данном алгоритме не предусмотрено движение по диагонали.
//==============================================================================
//1) Занести клетки в массив.
SUB(name1)
ARRPUSH($ARR,0)
FOR($A=1, $A<18)                        //Кол-во рядов.
FOR($B=1, $B<15)                        //Кол-во строк.
IF(STRCUT(TFREAD("system\Map\Map2.txt",$B),$A,1)>0)//Клетка.
INC($C,1)
$D=TFREAD("system\Map\Map1.txt",$C)                 //Идентификатор орентира.
ELSE
$D=0
END_IF
ARRPUSH($ARR,$D)
END_CYC
END_CYC
END_SUB
//==============================================================================
//3) Подсчет значения H для соседних клеток.
SUB(name3)
$C=($XT-1)*$YT
IF($ARR[$C]!0)
$Dir1=DIST($XT-1,$YT,$XK,$YK)
ELSE
$Dir1="Wall"
END_IF
$C=$XT*($YT+1)
IF($ARR[$C]!0)
$Dir2=DIST($XT,$YT-1,$XK,$YK)
ELSE
$Dir2="Wall"
END_IF
$C=($XT+1)*$YT
IF($ARR[$C]!0)
$Dir3=DIST($XT+1,$YT,$XK,$YK)
ELSE
$Dir3="Wall"
END_IF
$C=$XT*($YT-1)
IF($ARR[$C]!0)
$Dir4=DIST($XT,$YT+1,$XK,$YK)
ELSE
$Dir4="Wall"
END_IF
END_SUB
//==============================================================================
//4) Выбрать короткий путь.
SUB(name4)
UNDEFINE($analiz)
ARRPUSH ($analiz,$Dir1)
ARRPUSH ($analiz,$Dir2)
ARRPUSH ($analiz,$Dir3)
ARRPUSH ($analiz,$Dir4)
PRINT("analiz0=",$analiz[0])
PRINT("analiz1=",$analiz[1])
PRINT("analiz2=",$analiz[2])
PRINT("analiz3=",$analiz[3])
$min = 99999999999
FOR($a=0,$a < ARRSIZE($analiz))
 IF(($analiz[$a]!"Wall")=1)
   IF($analiz[$a] < $min)
      $min = $analiz[$a]
      UNDEFINE($names)
      ARRPUSH($names, $a)
   ELSE
      IF($analiz[$a] = $min)
         ARRPUSH($names, $a)
      END_IF
   END_IF
 END_IF
END_CYC
$name = $names[RND(0,ARRSIZE($names)-1)]
SWITCH($name)
case(0)
LCLICK(170,300)
case(1)
LCLICK(511,25)
case(2)
LCLICK(850,300)
case(3)
LCLICK(511,485)
END_SWITCH
END_SUB
//==============================================================================
//2) Определить текущую клетку.
SUB(name2)
$A=PXLCRC(497,522,523,523)
 IF($B!$A)
 $B=$A
  FOR($C=1,$C!ARRSIZE($ARR))
   IF(($A=$ARR[$C])=1)
   $XT=INT($C/14)-6
   $YT=$C-(INT($C/14)*14)-4
   PRINT("$XT=",$XT)
   PRINT("$YT=",$YT)
   END_IF
  END_CYC
  IF(($XT=$XK)&($YT=$YK))
  HALT                     //<<-- HALT Надо будет заменить
  GOTO(name0)              //<<-- Это все же будет поток...
  END_IF
  name3()
  name4()
  END_IF
WAIT(8)
END_SUB
//==============================================================================
//Программа.
name0:
$XK=0
$YK=3
name1()
WHILE(1)
GETSCREEN
name2()
END_CYC
« Last Edit: April 13, 2015, 02:13:58 PM by NStra »
Тут должна быть подпись...

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
До алгоритма не дошёл. Остановился здесь

Code: (clickermann) [Select]
$XT = INT($C/14) - 6
$YT = $C - (INT($C/14) * 14) - 4

Непонятно, что мы так высчитываем. Почему делим на 14? что это даст?
$C у нас номер по порядку, идём по рядам. В конце первого ряда $C = 17, в конце второго 34...
почему мы делим на количество рядов? По идее мы должны делить на количество "В РЯДУ", т.е.17

И что такое -6 и -4  ?

Отступление. Зачем мы здесь сравниваем с 1?
Code: (clickermann) [Select]
IF(($A = $ARR[$C]) = 1)
результат ничем не отличается от
Code: (clickermann) [Select]
IF($A = $ARR[$C])
И скрины бы рабочие, где там что считаем.


NStra

  • Освоившийся
  • **
  • Posts: 45
  • Подпись под аватаром.
    • View Profile
Quote
$XT = INT($C/14) - 6
$YT = $C - (INT($C/14) * 14) - 4
Это текущие координаты...Кхм, этот кусочек работает правильно=\
-6 и -4 это отступы, так как координаты начинаются не с 0,0 а -6,-3
Скрин в студию...
Тут должна быть подпись...