2012-04-09 13 views
2

Для моей программы мне нужно составить список списков с каждой подспиской, содержащей 2 числа, X и Y вместе с суммой и произведением этих двух чисел. До сих пор у меня есть следующие:Список проблем с построением

genList(95, X,[]):-!. 
genList(N, X,[[X,Y,Sum,Product]|Xs]):- 
    Y is N+1, 
    Sum is X+Y, 
    Sum<101, 
    Product is X*Y, 
    N1 is N+1, 
    genList(N1, X,Xs). 

Это прекрасно работает для моего тестового случая GenList (5,5, Q). Однако у меня возникли проблемы с его работой для любого стартового номера.

Цель состоит в том, чтобы найти каждую пару чисел, где сумма < = 100. Таким образом, проходит через выше для одного начального значения, Х найдет каждую пару 1 < < X Y, где сумма < = 100, и проходит через него со всеми числами 2-N дал бы полный список возможных пар.

Для тех, кто заинтересован, проблема я работаю через это проблема сумма/продукт, описанный here (второй на странице)

Если кто-то может помочь с этим было бы весьма признателен!

Кроме того, невозможно использовать встроенные предикаты пролога, а значит, сложный способ сделать это, а не с помощью findall.

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

[[5,6,11,30], [5,7,12,35], [5,8,13, 40], [5,9,14,45], [5,10,15,50], [5,11,16,55], [5,12,17,60], [5,13,18, 65], [5,14,19,70], [5,15,20,75], [5,16,21,80], [5,17,22,85], [5,18,23, 90], [5,19,24,95], [5,20,25,100], [5,21,26,105], [5,22,27,110], ...

EDIT:

Итак, после некоторого редактирования, вот последняя версия моего кода.

Я думаю, что это очень близко, но все еще что-то не так.

Он циклически проходит через пары чисел, но требует использования ";" для просмотра всех ответов, чего я не хочу. Кроме того, он возвращает false после того, как все ответы исчерпаны. Я просто не могу понять.

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

Э.Г. GenList (0,48,48, Q). дает мне:

[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[48,52,100,2496]] 
[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[48,52,100,2496],[49,50,99,2450],[49,51,100,2499]] 
[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[49,50,99,2450],[49,51,100,2499]] 
[[48,49,97,2352],[48,50,98,2400],[49,50,99,2450],[49,51,100,2499]] 
[[48,49,97,2352],[49,50,99,2450],[49,51,100,2499]] 
[[49,50,99,2450],[49,51,100,2499]] 
false. 

Как вы можете видеть, подсписок удаляется каждый раз, я просто не понимаю, почему!

ответ

1

Вы можете использовать Пролог возвратов здесь. Просто укажите, что вы хотите. Например, вы могли бы сказать:

  • Я хочу X быть между 1 и 100.
  • Я хочу Y быть между 1 и min(100 - X, X).
  • тогда я хочу их пара

Давайте посмотрим на то, что validPair/1 предикат будет выглядеть следующим образом:

validPair(X-Y) :- 
    between(1, 100, X), 
    Limit is min(100 - X, X), 
    between(1, Limit, Y). 

Вы можете назвать его просто с

?- validPair(X). 

и просматривать результаты с ; , или создать список всех совпадающих пар с findall/3.

Edit: даже с помощью рекурсии, мы можем держать наши заявления:

  • Я хочу X быть между 1 и 100.
  • Я хочу Y быть между 1 и min(100 - X, X).
  • тогда я хочу их пара

Таким образом, идея сделать это было бы создать уборщица предикат:

validPair(Result) :- 
    validPair(0, 0, Result). 
validPair(X, Y, R) :- 
    ... 

затем установить базовый случай:

validPair(101, _Y, []) :- !. 

и в рабочем предикате для выполнения заявлений, которые мы сделали с некоторыми условиями:

validPair(X, Y, [SomeStuff|R]) :- 
    X =< 100, 
    Limit is min(100 - X, X), 
    Y =< Limit, 
    !, 
    % we can go on and increment Y once we're finished 
    validPair(X, NextY, R). 
validPair(X, Y, R) :- 
    % if we come here that means that Y is finished growing and 
    % we have to increment X 
    NextX is X + 1, 
    validPair(NextX, 0, R). 
+0

Ах да, дело в этой программе, нам не разрешено использовать какие-либо прологи-встроенные, кроме арифметики и разреза. Возможно, это должно было бы упомянуть об этом! – XavierNuquos

+0

Спасибо Мог. Это почти есть, однако здесь ограничивающий фактор состоит в том, что сумма <100, а не x <= 100. Я извиняюсь, так как я заметил в своем оригинальном посте, что огромный кусок был опущен: «Цель состоит в том, чтобы найти каждую пару чисел, где sum <= 100. Таким образом, пропустив вышеприведенное для одного стартового значения, X найдет каждую пару 1 XavierNuquos

+0

Ха-ха, я полагаю, нет, просто в моих попытках я закончил с «ложным» возвратом, как и в моем другом вопросе: (Это раздражает, потому что это так близко к тому, что мне нужно, но я просто могу " я заработаю еще кое-что и вернусь сюда, если это еще не происходит ... – XavierNuquos

1

У меня такое чувство, что вы решаете проблему не так; Должен признаться, я не совсем понимаю, что делает ваш предикат.

Цель состоит в том, чтобы найти каждую пару чисел, где сумма < = 100.

Предполагая, что вы имеете в виду неупорядоченные пары неотрицательных целых чисел, это

between(0, 100, Sum), 
between(0, Sum, X), 
Y is Sum - X, 
X =< Y. 

Множество всех таких пар (в виде списка), то можно построить с findall/3.

Вы также можете сделать это с помощью CLP (FD):

use_module(library(clpfd)). 
[X, Y, Sum] ins 0..100, 
X #=< Y, 
X + Y #= Sum, 
label([X,Y,Sum]). 
Смежные вопросы