2013-11-02 2 views
2

Ho do I квадратные числа в списке в прологе?Пролог: квадратные числа в списке

Список может содержать числа, атомы и списки.

, например: [a,b,2,3,4,[3],[c,d,9]] и ответ должен быть [a,b,4,9,16,[3],[c,d,9]]. Как мы видим в ответе, это должно быть мелкое квадратирование значений в списке.

2-> 4

3-> 9

4-> 16

То, что я пытался до сих пор,

square([],X). 
square([A|B],X):-number(A), A is A*A, square(B,X). 

Х будет содержать в квадрат значений. Базовый регистр - это когда получен пустой список. Я проверяю, является ли голова (A) числом, затем я перехожу к квадрату числа и меняю A на A * A. Затем продолжайте и вызовите квадратную функцию для оставшейся части B.

Пожалуйста, предложите, где я делаю неправильно.

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

squared_members([], []). 
squared_members([L|Ls], [SqrdL|SqrdLs]) :- 
    number(L), 
    SqrdL is L * L, 
    squared_members(Ls, SqrdLs). 
squared_members([L|Ls], [L|SqrdLs]) :- 
    \+number(L), 
    squared_members(Ls, SqrdLs). 

И

squared_members([], []). 
squared_members([L|Ls], [M|Ms]) :- 
    (number(L) 
    -> M is L * L, squared_members(Ls, Ms) 
    ; M = L, squared_members(Ls, Ms) 
). 
+2

Я считаю, что эта проблема совсем недавно появился: http://stackoverflow.com/questions/19736345/кв-все-члены-в-список, в том числе-подсписке-пролог-без помощи-MapList. Ваш 'square ([A | B], X)' имеет пару проблем. Во-первых, вы не можете переназначить переменную в Prolog. После создания экземпляра они остаются. Во-вторых, после того, как вы построили квадрат «A», вы пройдете результат, так как вы не можете изменить исходный список ввода по той же причине. – lurker

+1

mbratch спасибо, что направил меня на это решение. Это глубокий предикат для возведения в квадрат. Я пытаюсь сделать мелкий предикат. Однако это помогло. – celeritas

ответ

3

мы определим предикат, который описывает отношения между одним списком, A, и другой список, B: B должны иметь все те же элементы, что и А, за исключением, что любое число А должно быть в квадрате в В.

Где вы пошли не так:

  • вашей землю с ondition, square([],X), говорит, что когда A пусто, тогда B - это что угодно (так, например, даже что-то вроде square([], 15) истинно). Но это не отражает тот смысл, который нам нужен, поскольку второй аргумент должен быть списком с тем же числом членов, что и первый. То есть, когда первый список пуст, тогда второй список должен быть пустым.
  • Та же проблема возникает с рекурсивным правилом, так как на каждой итерации, неопределенная переменная передается вместе, и никогда нет ничего, сказал об отношениях между первым списком и второй.
  • Это правило только успеха, если первый элемент ALIST является числом. В случае, когда первым элементом является, например, a (как в вашем примере), number(a) будет ложным. Поскольку для предиката нет дополнительных правил, оно будет просто ложным, если только каждый член первого списка не является числом.
  • Переменные в Prolog всегда должны иметь одинаковое согласованное значение во всем контексте, в котором они отображаются. Они функционируют как переменные в арифметической формуле.Формула + б - б = верно при любых значениях и б но * только если и б каждый назначается один, в соответствии значение на протяжении всего уравнение. То же самое верно в операторах Prolog формы <variable> is <expression>. Что вы написали: a = a * a, которого не может быть.

То, что вы говорите, это примерно так: список B представляет собой квадрат версии списка A, если A - пустой список, а B - это что-то ИЛИ, если первый элемент A - это число , и это число равно себе квадрат, и B является квадратом версия остальной части А.

Вот один из возможных решений:

squared_members([], []). 
squared_members([L|Ls], [SqrdL|SqrdLs]) :- 
    number(L), 
    SqrdL is L * L, 
    squared_members(Ls, SqrdLs). 
squared_members([L|Ls], [L|SqrdLs]) :- 
    \+number(L), 
    squared_members(Ls, SqrdLs). 

Обратите внимание, что это определение может установить значимые отношения между два списка, если они либо разделяют переменные, либо содержат элементы, связанные цепочкой отношений (т. е. SqrdL связан с L в силу того, что L * L). Это определение имеет еще одно предложение, а затем ваше, что позволяет ему учитывать элементы списка, которые не являются числами: они добавляются во второй список без изменений.

Альтернативное определение, с использованием If-Then-Else обозначения для чистого выражения, будет следующее:

squared_members([], []). 
squared_members([L|Ls], [M|Ms]) :- 
    (number(L) 
    -> M is L * L, squared_members(Ls, Ms) 
    ; M = L, squared_members(Ls, Ms) 
). 
+1

Спасибо @aBathologist. Это очень подробное объяснение. И я это понимаю. Однако в 3-предикатной программе во втором предикате вы используете, Ms -> Я думаю, что это должно быть Ls, не должно быть? – celeritas

+0

@celeritas Я рад, что это помогло! Ты прав насчет этой опечатки! (Это предикат 2-арности, tho). Я исправил это. Спасибо, что указали это. –

+0

Что такое \ + в squared_members ([L | Ls], [L | SqrdLs]): - \ + номер (L), squared_members (Ls, SqrdLs). – akashchandrakar

Смежные вопросы