Author Topic: Найти элегантное решение  (Read 5178 times)

0 Members and 1 Guest are viewing this topic.

Svarog

  • Освоившийся
  • **
  • Posts: 25
    • View Profile
Найти элегантное решение
« on: January 03, 2016, 12:45:14 PM »
Всем привет) Вопрос такой...Есть пять координат (5 сундучков), которые иногда попадаются в игре. Расположены на экране как точки на кубике на грани "Пятерка". Необходимо открыть (кликнуть)  3 из 5-ти сундучков (каждый раз кликать разные). Я так понимаю, что всего вариантов будет 12 шт, можно конечно все это забить в алгоритм, типа выбираем рандомно от 1 до 12 и если "1", то кликать 3 раза в такие-то координаты, если "2", то 3 раза в другие и так далее. Но как-то это не красиво... Вот уверен, что существует элегантное решение этой задачи, а мозга не хватает найти его. Посему прошу помощи у гуру  :)

Svarog

  • Освоившийся
  • **
  • Posts: 25
    • View Profile
Re: Найти элегантное решение
« Reply #1 on: January 03, 2016, 01:25:22 PM »
Просто, любые 3 из 5-ти.

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Найти элегантное решение
« Reply #2 on: January 03, 2016, 02:20:16 PM »
Координаты кликов только свои впиши
Code: (clickermann) [Select]
$r = "12345"
FOR($a=0,$a<3)
   $f = INT(STRCUT($r,RND(1,STRLEN($r)),1))
   IF(STRLEN($r) > 1)
      $r = INT(STRFILTER ($r, $f, 0))
   END_IF
   SWITCH($f)
   CASE(1)
      LCLICK(10,10)
   CASE(2)
      LCLICK(10,10)
   CASE(3)
      LCLICK(10,10)
   CASE(4)
      LCLICK(10,10)
   CASE(5)
      LCLICK(10,10)
   DEFAULT
   END_SWITCH
   WAITMS(50)
END_CYC

HALT
« Last Edit: January 03, 2016, 02:23:49 PM by Oraven »

Svarog

  • Освоившийся
  • **
  • Posts: 25
    • View Profile
Re: Найти элегантное решение
« Reply #3 on: January 03, 2016, 05:16:46 PM »
Oraven, огромное спасибо, именно то что нужно! Работает суперпупер  :D

Doda

  • Guest
Re: Найти элегантное решение
« Reply #4 on: January 11, 2016, 03:05:29 AM »
Code: (clickermann) [Select]
print("Погнали")
for($i=0,$i<3)
   $open=rnd(1,5)
      for($o,$o<arrsize($sunduk))
      if  (arrsize($sunduk)<2)
         if ($open=$sunduk[$o])
            WHILE($open=$sunduk[$o])
               $open=rnd(1,5)
            end_cyc
         END_IF
      else
         if (($open=$sunduk[0])| ($open=$sunduk[1]))
            WHILE(($open=$sunduk[0])| ($open=$sunduk[1]))
               $open=rnd(1,5)
            end_cyc
         END_IF
      END_IF
   end_cyc
   arrpush($sunduk, $open)
      print($sunduk[$i])
   SWITCH($open)
   CASE(1)
      LCLICK(10,100)
   CASE(2)
      LCLICK(10,200)
   CASE(3)
      LCLICK(10,300)
   CASE(4)
      LCLICK(10,400)
   CASE(5)
      LCLICK(10,500)
   DEFAULT
   END_SWITCH
   click
end_cyc
halt
« Last Edit: January 11, 2016, 03:13:56 AM by Браm комара »

Doda

  • Guest
Re: Найти элегантное решение
« Reply #5 on: January 11, 2016, 03:15:51 AM »
ух, какое у меня неэлегантное решение вышло))  я голову ломал долго, все таки алгоритмист из меня хреновый

Doda

  • Guest
Re: Найти элегантное решение
« Reply #6 on: January 11, 2016, 11:30:32 AM »
лишний клик я видел.. лень было убирать уже ::) вариант выше я не понял, не работал такими функциями ни разу. А за похвалу спасибо, мне приятно) только код вышел длинноватый
« Last Edit: January 11, 2016, 11:33:14 AM by Браm комара »

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Найти элегантное решение
« Reply #7 on: January 11, 2016, 04:05:10 PM »
лишний клик я видел.. лень было убирать уже ::) вариант выше я не понял, не работал такими функциями ни разу. А за похвалу спасибо, мне приятно) только код вышел длинноватый
Такой рандом без повторов ограничен 10 числами.
Code: (clickermann) [Select]
$r = "1234567890"
FOR($a=0,$a<10)
   $f = INT(STRCUT($r,RND(1,STRLEN($r)),1)) // здесь вырезаем из строки $r случайный символ и записываем в $f
   IF(STRLEN($r) > 1) // если длинна строки $r больше одного
      $r = INT(STRFILTER ($r, $f, 0)) // отфильтровываем вырезанный символ (удаляем) и записываем полученную строку снова в $r
   END_IF   
   LOGWRITE ($f) // в $f у нас выводятся полученные случайные числа
   // таким образом каждый проход строка $r будет все короче пока не дойдет до 1
END_CYC
HALT

Doda

  • Guest
Re: Найти элегантное решение
« Reply #8 on: January 12, 2016, 12:37:36 AM »
а вот элегантное решение массивом) самое элегантное..для любых задач, для любого количества чисел.
Code: (clickermann) [Select]
FOR($a, $a < 5) //5 раз цикл
   ARRPUSH($klik, $a+1)//создаем массив с числами от 1 до 5
END_CYC

FOR($b, $b < 3)//выбираем 3 числа
   while ($m=0)
$u=RND(1,ARRSIZE($klik)-1)
    $m =  $klik[$u]
   END_CYC
   print($m) //вместо этого вставь клики)) работает как часики
   $klik[$u]=0
   UNDEFINE($m)
END_CYC
halt
« Last Edit: January 12, 2016, 07:33:54 AM by Oraven »

Doda

  • Guest
Re: Найти элегантное решение
« Reply #9 on: January 12, 2016, 12:45:09 AM »
Такой рандом без повторов ограничен 10 числами.

Спасибо за разъяснения!, буду применять данный способ)

Doda

  • Guest
Re: Найти элегантное решение
« Reply #10 on: January 12, 2016, 01:00:40 AM »
вид циклов для версии 4.11 исправлен
нумерация элементов массива начинается с  0
проверяй результат работы скрипта тщательнее и такие простые недостатки выявишь сам.
В этом коде  нет ни единой ошибки :o :o И при чем здесь нумерация?) насчет нумерации все понятно, но где в примере вы видите обращение вместо нулевого  элемента, к первому?
« Last Edit: January 12, 2016, 01:03:24 AM by Браm комара »

Doda

  • Guest
Re: Найти элегантное решение
« Reply #11 on: January 12, 2016, 01:21:14 AM »
да, увидел. рандомный диапазон по умолчанию поставил от единицы. Все, готово! добавил чистку массива. Подскажите как без стэка очистить массив?   может андефайном? или ничего не реализовано
Code: (clickermann) [Select]
FOR($a=0, $a < 5) //5 раз цикл
   ARRPUSH($klik, $a+1)//создаем массив с числами от 1 до 5
END_CYC
 
FOR($b=0, $b < 3)//выбираем 3 числа
   while ($m=0)
      $u=RND(0,ARRSIZE($klik)-1)
      $m =  $klik[$u]
   END_CYC
   print($m) //вместо этого вставь клики)) работает как часики
   $klik[$u]=0
   UNDEFINE($m)
END_CYC
 FOR($p=0, $p < ARRSIZE($klik))// чистим массив
  $z=arrpop($klik)
   UNDEFINE($z)
END_CYC

  print("")
« Last Edit: January 12, 2016, 01:38:28 AM by Браm комара »

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Найти элегантное решение
« Reply #12 on: January 12, 2016, 07:40:10 AM »
да, увидел. рандомный диапазон по умолчанию поставил от единицы. Все, готово! добавил чистку массива. Подскажите как без стэка очистить массив?   может андефайном? или ничего не реализовано

Как раз таки UNDEFINE убивает как переменные так и массивы.

Code: (clickermann) [Select]
FOR($a=0, $a < 5) //5 раз цикл
   ARRPUSH($klik, $a+1)//создаем массив с числами от 1 до 5
END_CYC

FOR($b=0, $b < 3)//выбираем 3 числа
   while ($m=0)
      $u=RND(0,ARRSIZE($klik)-1)
      $m =  $klik[$u]
   END_CYC
   print($m) //вместо этого вставь клики)) работает как часики
   $klik[$u]=0
   $m = 0
END_CYC

UNDEFINE($klik) // чистим массив

print("")

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Найти элегантное решение
« Reply #13 on: January 12, 2016, 07:55:38 AM »
а вот элегантное решение массивом) самое элегантное..для любых задач, для любого количества чисел.

Элегантное? Чем? Тем что тычем рандомайзом "в небо" пока не наткнёмся на не обнулённый элемент?
Ну на пяти элементах то фиг с ним, хотя и так не стоит делать. А если их будет 1000 или не дай бог больше? И выбрать нужно много, допустим все.
Сколько будем ждать этот цикл?

Самое простое и очивидное это сделать два массива и перекладывать из одного в другой. Но нет прямых команд для удаления произвольного элемента массива.
Хоть бы и были или свои сдвиги это энергозатратная операция.

Решения удобные и универсальные придумали давно.
http://crapware.aidf.org/forum/index.php?topic=1797.msg10535#msg10535
http://crapware.aidf.org/forum/index.php?topic=1965.msg11731#msg11731
« Last Edit: January 12, 2016, 08:09:47 AM by Vint »


Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Найти элегантное решение
« Reply #14 on: January 12, 2016, 08:07:50 AM »
а вот элегантное решение массивом) самое элегантное..для любых задач, для любого количества чисел.

Элегантное? Чем? Тем что тычем рандомайзом "в небо" пока не наткнёмся на не обнулённый элемент?
Ну на пяти элементах то фиг с ним, хотя и так не стоит делать. А если их будет 1000 или не дай бог больше? И выбрать нужно много, допустим все.
Сколько будем ждать этот цикл?

А я уже проверил  :D Не так долго

Code: (clickermann) [Select]
$ms = $_ms

FOR($a=0, $a < 1000)
   ARRPUSH($klik, $a+1)
END_CYC

$siz = ARRSIZE($klik)-1
FOR($b=0, $b < 1000)
   while ($m=0)
      $u=RND(0,$siz)
      $m =  $klik[$u]
   END_CYC
   //   print($m)
   $klik[$u]=0
   $m = 0
END_CYC

UNDEFINE($klik)

LOGWRITE ("Вариант 1: ", $_ms-$ms, " мс")

$ms = $_ms
// вариант рандомизации массива
UNDEFINE($arr)
FOR($a=0,$a<1000)
   ARRPUSH($arr, $a+1)
END_CYC

$i = ARRSIZE($arr)-1
WHILE($i>0)
   $j = RND(0,$i)
   IF($i ! $j)
      $tmp = $arr[$j]
      $arr[$j] = $arr[$i]
      $arr[$i] = $tmp
   END_IF
   INC($i,-1)
END_CYC

// здесь используем рандомизированный массив $arr

LOGWRITE ("Вариант 2: ", $_ms-$ms, " мс")
LOGWRITE (" ")

HALT

Code: [Select]
8:58:47 Вариант 1: 4469 мс
8:58:50 Вариант 2: 2508 мс
8:58:50 
9:00:58 Вариант 1: 8285 мс
9:01:01 Вариант 2: 2540 мс
9:01:01 
9:01:09 Вариант 1: 7415 мс
9:01:12 Вариант 2: 2554 мс
9:01:12 
9:01:23 Вариант 1: 9900 мс
9:01:25 Вариант 2: 2585 мс
9:01:25 
9:01:36 Вариант 1: 9805 мс
9:01:38 Вариант 2: 2529 мс
9:01:38 
9:04:22 Вариант 1: 8898 мс
9:04:25 Вариант 2: 2492 мс
9:04:25