2016-03-31 7 views
1

Я пытаюсь создать список со случайными значениями от 1 до 10, но когда я запускаю код, я получаю «ложь» ...пролога - генерировать список со случайными значениями

geraL(0,_). 
geraL(C,Y):- 
    C is C-1, 
    random(1,10,U), 
    Y = [U|Y], 
    geraL(C,Y). 


?-geraL(13,X). 
+0

Я использую эту платформу ... http://pengines.swi-prolog.org/apps/swish/ – mglgiordani

+0

@SQB Да, плохая привычка.:) Он начинается как один комментарий комментария и расширяется до ответа ... – lurker

+2

'findall (U, (между (1, N, _), random (1,10, U)), Us)' - редкий случай, когда findall имеет смысл. – false

ответ

2

Мы будет покрывать каждую проблему в отдельности:

  • geraL(0, _) говорит, что если вы хотите ноль случайных чисел, все, что может быть результатом. Я уверен, это не то, что вы имеете в виду. Каким должен быть результат, если число элементов равно 0?

  • Вы должны иметь ограничение, которое говорит C > 0 в вашем общем случае, чтобы избежать выполнения этого правила, когда это не требуется

  • C is C - 1 всегда будет терпеть неудачу, потому что при любом значении C, C и C-1 никогда не могут быть одинаковыми стоимость. Вы не можете переустановить переменную, если она имеет значение в предложении предиката, кроме как с помощью обратного отслеживания.

  • Хотя допустимо Y = [U|Y], это циклическое определение списка (список, определенный в терминах самого себя с дополнительным элементом главы), и я уверен, что это не то, что вы хотите.

Если вы исправите эти пункты, ваша программа будет работать. Первые два фиксируются с использованием вспомогательной (другой) переменной. Последний из них правильно определяет базовый случай, чтобы связать пустой список с 0, а не анонимной переменной.

geraL(0, []). % Fix for item 1: zero values should be an empty list 
geraL(C, Y):- 
    C > 0,  % Fix for item 2 
    C1 is C-1, % Fix for item 3: use C1 for the new value 
    random(1, 10, U), 
    Y = [U|T], % Fix for item 4: use T for the new value (tail) 
    geraL(C1, T). 
+2

У меня было 'geraL (0, []): -! .' вместо добавленного условия' C> 0', но последнее лучше, поскольку оно определяет ограничение вместо управления потоком. +1 – SQB

+1

@ SQB. Остерегайтесь [tag: proog-cut]: он часто заставляет код потерять стойкость. (Это не в этом конкретном случае.) – repeat

+0

@lurker: знаете ли вы, что обмен двумя статьями будет: 1. сделать ваш код детерминированным, без остаточного выбора, 2. сделать его даже немного быстрее во многих прологах, поскольку предложение - индексирование может быть использовано? – false

0

Существует встроенный предикат findnsols/4 который находит самое большее N решений.

Этот предикат может использоваться для эквивалента цикла. Поскольку random/3 является детерминированным, нам нужно добавить repeat/0 в цель, чтобы повторить его.

geraL(C, Y) :- findnsols(C, U, (repeat, random(1, 10, U)), Y). 

Кроме того, обратите внимание, что random/3 устарел в SWI Prolog; рекомендуется вместо этого использовать random/1 или random_between/3.
В частности, random/3 исключает верхнюю границу, поэтому random(1, 10, U) никогда не даст U = 10.

+0

Для меня использование 'findnsols/4' в этом контексте не представляется разумным выбором. – repeat

+1

'findnsols/4' представляет собой комбинацию двух довольно ненадежных абстракций:' findall/3', который имеет целую кучу проблем с квантованием w.r.t и 'call_nth/2'. – false

+1

'random/3' может считаться устаревшим SWI, но' random_between/3' недоступен из коробки с SICStus (подробности: https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus .html/lib_002drandom.html). Поэтому, если ваш код должен работать как с SWI, так и с SICStus, лучше используйте 'random/3' ... – repeat

4

Не нужно писать рекурсивный код!

random/3 Просто используйте, length/2 и maplist/2 так:

 
?- length (Zs, 13), maplist (random (0,10), Zs). 
Zs = [8, 9, 3, 5, 0, 7, 6, 7, 9, 9, 2, 4, 7]. 

?- length(Zs, 13), maplist(random(0,10), Zs). 
Zs = [1, 7, 7, 6, 2, 5, 2, 9, 9, 2, 0, 7, 1]. 

?- length(Zs, 13), maplist(random(0,10), Zs). 
Zs = [4, 6, 7, 0, 1, 3, 4, 9, 0, 8, 3, 8, 5]. 

?- length(Zs, 13), maplist(random(0,10), Zs). 
Zs = [3, 1, 2, 1, 5, 3, 9, 8, 3, 7, 8, 1, 7]. 

Примечание примеси! Мы получаем разные ответы - по крайней мере, большую часть времени ...

Для воспроизводимых результатов запишите фактический метод и его начальное состояние, .

+1

Очевидно, что лучший ответ! – false

+2

@false это лучший способ решить оригинальную проблему, которая делает ее отличным дополнением к списку ответов. Но цель моего первоначального ответа заключалась в том, чтобы напрямую рассмотреть вопрос о том, почему их реализация не сработала. – lurker

+1

@repeat, разве не желательно, чтобы генератор случайных списков чисел не имел воспроизводимых результатов? :) – lurker