Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

задача из Haskell

360  1 2 все
Kvint постоялец20.04.14 10:38
Kvint
NEW 20.04.14 10:38 
Всем привет.
прошу помочь с решением задачи
условия следующие:
Robert der Rollenspieler möochte die Wahrscheinlichkeit berechnen, dass seine Spiel gur eine
Fertigkeitsprüfung besteht, um die nächste Aufstufung seiner Spiel gur zu planen. In seinem
Spiel wird eine Fertigkeitsprüfung wie folgt durchgeführt: Gegeben sind drei Attribute
der Spiel gur und eine Schwierigkeit. Robert muss jeden der drei Attributswerte mit einem
20-seitigen Würfel (Zahlen von 1{20) unterwürfeln. Für jeden der drei Würfelwürfe wird die
Di erenz notiert, falls der Würfel über dem Fähigkeitswert liegt und 0 sonst. Die Prüfung
gelingt, wenn die Summe der abgeschnittenen Di erenzen kleiner oder gleich dem Schwierigkeitswert
ist. Zusätzlich gilt, dass die Prüfung immer gelingt, wenn mindestens zwei der drei
Würfelwürfe eine 1 ergeben haben; aber die Prüfung misslingt auch schon, falls 2  20 füallt.
Я прописал условия в списке:
erfolgG (a1,a2,a3) n = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20], x+y<40, x+z<40, y+z<40,
if x-a1<=0
then (x-a1) == 0
else (x-a1) == (x-a1),
if y-a2<=0
then (y-a2) == 0
else (y-a2) == (y-a2),
if z-a3<=0
then (z-a3) == 0
else (z-a3) == (z-a3),

(x-a1)+(y-a2)+(z-a3)<=n]
Но вывод комбинаций выходит не полный, а именно при данных (2,2,3) 3 Hskell выводит [(2,2,3),(2,2,4),(2,2,5),(2,2,6),(2,3,3),(2,3,4),(2,3,5),(2,4,3),(2,4,4),(2,5,3),(3,2,3),(3,2,4),(3,2,5),(3,3,3),(3,3,4),(3,4,3),(4,2,3),(4,2,4),(4,3,3),(5,2,3)]
Исходя из условий задачи комбинаций должно быть больше, например (1,1,1) при ручном пересчете: 1<2 -> 0, 1<2 -> 0, 1<3 -> 0 , 0+0+0=0 < 3. Я это отразил в условиях (отмечено зеленым), но похоже не правильно. Помогите плз, разрбраться.
Так же не получается приклееть к списку считалку всех выриантов:
summE [] = 0
summE erfolgG = 1 + length (tail erfolgG)
прошу помочь
#1 
AlexOtt местный житель21.04.14 20:25
AlexOtt
NEW 21.04.14 20:25 
в ответ Kvint 20.04.14 10:38
что-то я из немецкого текста не особо понял - есть по русски или английски?
насчет считалки результатов - зачем так сложно, если нужна длина, то почему просто не взять length и применить к результату?, типа
summE = length
ну или если хочется самому считать, то уж тогда
summE [] = 0
summE (x:xs) = 1 + summE xs
#2 
MrSanders свой человек21.04.14 22:19
NEW 21.04.14 22:19 
в ответ Kvint 20.04.14 10:38, Последний раз изменено 21.04.14 22:37 (MrSanders)
Я правильно понял что вы пытаетесь сделать список с перебором всех подходящих бросков кубика? А потом для подсчета вероятности поделить длину списка на 20^3?
В ответ на:
erfolgG (a1,a2,a3) n = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20], x+y<40, x+z<40, y+z<40,
if x-a1<=0
then (x-a1) == 0
else (x-a1) == (x-a1),
if y-a2<=0
then (y-a2) == 0
else (y-a2) == (y-a2),
if z-a3<=0
then (z-a3) == 0
else (z-a3) == (z-a3),
(x-a1)+(y-a2)+(z-a3)<=n]

А если так? (сильно не бить, haskell давно не трогал :))
diff x a | x - а > 0 = х - а
| х - а <= 0 = 0
erfolgG (a1,a2,a3) n = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20], x+y<40, x+z<40, y+z<40,
(diff x a1)+(diff y a2)+(diff z a3) <= n]
Но. Про варианты с двумя выброшенными единицами вы забыли
Вам надо бы что-то вроде (с case-ом вроде понятнее)
check x y z a1 a2 a3 n = case (x,y,z) of
(1,1,_) -> True
(1,_,1) -> True
(_,1,1) -> True
(20,20,_) -> False
(20,_,20) -> False
(_,20,20) -> False
(_,_,_) -> (diff x a1)+(diff y a2)+(diff z a3) <= n
и
erfolgG (a1,a2,a3) n = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20], check x y z a1 a2 a3 n]
#3 
Kvint постоялец21.04.14 23:04
Kvint
NEW 21.04.14 23:04 
в ответ AlexOtt 21.04.14 20:25
Вот мой любительский перевод
Даны три характеристики (допустим Сила, Ловкость и Разум) и показатель сложности. Для каждой характеристики нужно бросить один раз двадцатисторонний кубик (1-20). Если кубик выдает число, большее чем показатель характеристики, то записывается разница меджу этими цифрами, в противном случае - ноль. Далее эти три разницы суммируются и сравниваются с показателем сложности. В случае, если сумма разниц меньше или равна показателю сложности, то это значит леведап.
По условиям задачи нужно показать все удачные комбинации и посчитать их. Но есть два исключения: 1. если кубик два раза из трех выпал на единицу - это считается тоже как победа, 2. если кубик два раза из трех выпал на двадцать - это неудача.
Про считалку не совсем понял, как это реализовать.
#4 
Kvint постоялец21.04.14 23:12
Kvint
NEW 21.04.14 23:12 
в ответ MrSanders 21.04.14 22:19
Я сам с haskell и программированием в целом занимаюсь не больше недели :)
сегодня проверил еще раз список, как оказалось эта часть не нужна
аif x-a1<=0
then (x-a1) == 0
else (x-a1) == (x-a1),
if y-a2<=0
then (y-a2) == 0
else (y-a2) == (y-a2),
if z-a3<=0
then (z-a3) == 0
else (z-a3) == (z-a3),
Все условия уже выполняются. Осталост только счетчик прикрепить, а вот это пока для меня сложновато
#5 
MrSanders свой человек21.04.14 23:22
NEW 21.04.14 23:22 
в ответ Kvint 21.04.14 23:12
Счетчик чего вам нужен-то? AlexOtt уже ж спросил почему вас родной length для списка не устраивает.
Да, и если вы просто выбросите условия "if x-a1<=0 ..." ничем их не заменив, то у вас проблемы будут.
Пример:
(5,5,5) 10 - в вашем списке появится, например, (2,2,20), хотя он по условиям задачи не подходит (0+0+15>10). Понимаете почему?
#6 
  digital.pilot патриот21.04.14 23:27
digital.pilot
NEW 21.04.14 23:27 
в ответ AlexOtt 21.04.14 20:25, Последний раз изменено 22.04.14 02:56 (digital.pilot)
В ответ на:

summE [] = 0
summE (x:xs) = 1 + summE xs

о, да это ж практически Пролог)
len([],0).
len([_|T],L) :- len(T,L1), L is L1 + 1.
#7 
Kvint постоялец22.04.14 00:01
Kvint
NEW 22.04.14 00:01 
в ответ MrSanders 21.04.14 23:22
Вы правы на счет нарушения условий задачи. Может быть как то так сделать?
Добавить три переменных, которые в зависимости от разницы будут единицей или нулем.
вот так:
(x-a1)<0 -> d1 == 0
(x-a1)>=0 -> d1 == 1
А потом эти переменные будут перемножать сами разницы:
d1*(x-a1)+d2*(y-a2)+d3*(z-a3) <= n
#8 
Kvint постоялец22.04.14 00:06
Kvint
NEW 22.04.14 00:06 
в ответ MrSanders 21.04.14 23:22
В ответ на:
Счетчик чего вам нужен-то?

мне нужно сумма всех удачных комбинаций, что бы вычислить вероятность поделив сумму удачных комбинаций на сумму всех существующих.
По последнему я сделал правиольно (я надеюсь)
allV = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20]]
summ :: [a] -> Int
summ [] = 0
summ allV = 1 + length (tail allV)
#9 
MrSanders свой человек22.04.14 00:42
NEW 22.04.14 00:42 
в ответ Kvint 22.04.14 00:06
В ответ на:
По последнему я сделал правиольно (я надеюсь)
allV = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20]]

Я вам даже облегчу жизнь :)
То что вы считаете (длина этого списка) это количество элементов в упорядоченной выборке с возвращением. Формула - n^k. Так что ваше число всех возможных комбинаций - 20^3.
В ответ на:
summ [] = 0
summ allV = 1 + length (tail allV)

А это вообще фееричная ерунда.
Вы написали:
summ x =
ЕСЛИ x = [] ВЕРНИ 0
ЕСЛИ x = allv ВЕРНИ 1 + ДЛИНА allv БЕЗ ПЕРВОГО ЭЛЕМЕНТА
а что вернет ваша функция если её вызвать как
summ 1:2:3:[]
?
А просто написать length allv вам что мешает-то?
#10 
Kvint постоялец22.04.14 08:03
Kvint
22.04.14 08:03 
в ответ MrSanders 22.04.14 00:42
Написал так:
allV :: [(Integer, Integer, Integer)]
allV = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20]]
summ :: [a] -> Int
summ allV = length allV
#11 
AlexOtt местный житель22.04.14 09:41
AlexOtt
NEW 22.04.14 09:41 
в ответ digital.pilot 21.04.14 23:27
дык, оба - декларативные языки с pattern matching... а если сюда еще и приплести Erlang ;-)
#12 
MrSanders свой человек22.04.14 09:58
NEW 22.04.14 09:58 
в ответ Kvint 22.04.14 08:03
А тепень делаем еще два шага
1. Осознаем что функция summ не нужна. Вместо нее можно просто писать length
2. Понимаем что вообще весь список allv нам не нужен. Его размер = 20*20*20. Поэтому везьде где мы собирались писать length allv мы просто пишем 8000.
#13 
Kvint постоялец22.04.14 10:10
Kvint
NEW 22.04.14 10:10 
в ответ MrSanders 22.04.14 09:58
Оставлю пока как есть, тк нужно будет лист сдавать.
Все эти вещи второстепенные, главная проблема еще не решена.
#14 
Kvint постоялец22.04.14 12:01
Kvint
NEW 22.04.14 12:01 
в ответ MrSanders 22.04.14 09:58
Для того, что бы высчитать вероятность я написал следующее, но как обычно не верно
chance (a1,a2,a3) n = summE/ 8000
where summE erfolgG (a1,a2,a3) n = length
where erfolgG (a1,a2,a3) n = [(x,y,z) | x<-[1..20], y<-[1..20], z<-[1..20], check x y z a1 a2 a3 n]
where check x y z a1 a2 a3 n = case (x,y,z) of
(1,1,_) -> True
(1,_,1) -> True
(_,1,1) -> True
(20,20,_) -> False
(20,_,20) -> False
(_,20,20) -> False
пробовал просто написать chance (a1,a2,a3) n = length (erfolgG (a1,a2,a3) n) / 8000
но тоже провал

#15 
MrSanders свой человек22.04.14 13:57
22.04.14 13:57 
в ответ Kvint 22.04.14 12:01
что-то у вас с синтаксисом не того (опять же, насколько я помню хэскел).
Давайте для начала вы протестируете функцию erfolgG с параметрами (2,2,2) 2 например. И проверьте что в сгенерированном списке будет.
#16 
Kvint постоялец22.04.14 14:45
Kvint
NEW 22.04.14 14:45 
в ответ MrSanders 22.04.14 13:57
Вот что получается. как вы и говорили есть комбинации не удовлетворяющие условаиям задачи
[(1,1,1),(1,1,2),(1,1,3),(1,1,4),(1,1,5),(1,1,6),(1,1,7),(1,1,8),(1,1,9),(1,1,10),(1,1,11),(1,1,12),(1,1,13),(1,1,14),(1,1,15),(1,1,16),(1,1,17),(1,1,18),(1,1,19),(1,1,20),(1,2,1),(1,2,2),(1,2,3),(1,2,4),(1,2,5),(1,3,1),(1,3,2),(1,3,3),(1,3,4),(1,4,1),(1,4,2),(1,4,3),(1,5,1),(1,5,2),(1,6,1),(1,7,1),(1,8,1),(1,9,1),(1,10,1),(1,11,1),(1,12,1),(1,13,1),(1,14,1),(1,15,1),(1,16,1),(1,17,1),(1,18,1),(1,19,1),(1,20,1),(2,1,1),(2,1,2),(2,1,3),(2,1,4),(2,1,5),(2,2,1),(2,2,2),(2,2,3),(2,2,4),(2,3,1),(2,3,2),(2,3,3),(2,4,1),(2,4,2),(2,5,1),(3,1,1),(3,1,2),(3,1,3),(3,1,4),(3,2,1),(3,2,2),(3,2,3),(3,3,1),(3,3,2),(3,4,1),(4,1,1),(4,1,2),(4,1,3),(4,2,1),(4,2,2),(4,3,1),(5,1,1),(5,1,2),(5,2,1),(6,1,1),(7,1,1),(8,1,1),(9,1,1),(10,1,1),(11,1,1),(12,1,1),(13,1,1),(14,1,1),(15,1,1),(16,1,1),(17,1,1),(18,1,1),(19,1,1),(20,1,1)]
Я не могу понять, как добавить список еще три переменные для обозначения разницы
#17 
MrSanders свой человек22.04.14 19:13
NEW 22.04.14 19:13 
в ответ Kvint 22.04.14 14:45
а код вы какой тестировали?
С функцией check?
Посмотрите что она выдает при вызове
check 1 2 5 2 2 2 2
И (на всякий случай) проверьте что вам выдаст
diff 1 2
diff 2 2
diff 5 2
Приложите полный код программы, которую вы тестируете, а то я уже запутался :)
#18 
Kvint постоялец22.04.14 20:17
Kvint
NEW 22.04.14 20:17 
в ответ MrSanders 22.04.14 19:13
Я сделал три функции diff1, diff2 и diff3. После этого все заработало в лучшем виде. Вот пример вывода при (2,2,2) 2
[(1,1,1),(1,1,2),(1,1,3),(1,1,4),(1,2,1),(1,2,2),(1,2,3),(1,2,4),(1,3,1),(1,3,2),(1,3,3),(1,4,1),(1,4,2),(2,1,1),(2,1,2),(2,1,3),(2,1,4),(2,2,1),(2,2,2),(2,2,3),(2,2,4),(2,3,1),(2,3,2),(2,3,3),(2,4,1),(2,4,2),(3,1,1),(3,1,2),(3,1,3),(3,2,1),(3,2,2),(3,2,3),(3,3,1),(3,3,2),(4,1,1),(4,1,2),(4,2,1),(4,2,2)]
Огромное спасибо за помощь, а то я уже отчаиваться начал. Не первый раз тут совет прошу, всегда выручают.
Осталось только вероятность посчитать, но это уж сам постараюсь сделать :)
#19 
MrSanders свой человек22.04.14 20:50
NEW 22.04.14 20:50 
в ответ Kvint 22.04.14 20:17
3 функции, которые одно и то же делают это плохо, надо стремиццо к совершенсву! :)
#20 
1 2 все