/* Doing arithmetic on lists of x's. */ ;;; Use "head" and "tail" instead of Pop-11's "hd" and "tl" vars procedure (head = hd, tail = tl); ;;; A number recognizer /* PROCEDURE: isnum (item) -> boole INPUTS : item is anything OUTPUTS : boole is a truth-value (boolean) USED IN : ??? CREATED : 30 May 2009 PURPOSE : Recognize a numeral in the form of a list that is either empty or contains only occurrences of the word "x". TESTS: isnum([x x x]) => ** isnum([]) => ** isnum([y y y]) => ** isnum([xx]) => ** */ define isnum(item) -> boole; lvars L; if islist(item) and item matches [] or (islist(item) and item matches ![x ??L:isnum]) then true else false endif -> boole; enddefine; ;;; A procedure for adding two nums /* PROCEDURE: addnums (num1, num2) -> sum INPUTS : num1, num2 Where : num1 is a num num2 is a num OUTPUTS : sum is a num USED IN : ??? CREATED : 30 May 2009 PURPOSE : add two numbers (as lists) returning the sum TESTS: addnums([], []) => ** [] addnums([x], []) => ** [x] addnums([x x], [x x x]) => ** [x x x x x] addnums([x x], [y y]) => ;;; MISHAP - Nums needed for addnums ;;; INVOLVING: [x x] [y y] ;;; FILE : /home/staff/axs/popd/nums.p LINE NUMBER: 77 ;;; DOING : addnums runproc addnums([xx], [xxx]) => ;;; MISHAP - Nums needed for addnums ;;; INVOLVING: [xx] [xxx] ;;; FILE : /home/staff/axs/popd/nums.p LINE NUMBER: 86 ;;; DOING : addnums runproc */ define addnums(num1, num2) -> sum; if isnum(num1) and isnum(num2) then if num1 matches [] then num2 -> sum elseif num2 matches [] then num1 -> sum else ;;; add an "x" to num1 and reduce one from num2 ;;; and add the two resulting lists addnums([ x ^^num1], tail(num2)) -> sum endif else mishap('Nums needed for addnums', [^num1 ^num2]); endif; enddefine; /* PROCEDURE: subnums (num1, num2) -> diff INPUTS : num1, num2 Where : num1 is a number num2 is a number OUTPUTS : diff is a number USED IN : ??? CREATED : 21 Jun 2009 PURPOSE : ??? if num1 is bigger than or equal to num2 then return a number which when added to num2 gives num1 TESTS: subnums( [], [] ) => ** [] subnums( [x], [] ) => ** [x] subnums( [], [x] ) => ;;; MISHAP - Nums cannot subtract from zero ;;; INVOLVING: [] [x] subnums( [x x x], [x] ) => ** [x x] subnums( [x x x], [x x x x] ) => ;;; MISHAP - Nums cannot subtract from zero ;;; INVOLVING: [] [x] ;;; FILE : /home/axs/popd/nums.p LINE NUMBER: 128 ;;; DOING : subnums(*4) runproc subnums( [x x x x], [x x x x] ) => ** [] */ define subnums(num1, num2) -> diff; if isnum(num1) and isnum(num2) then if num2 matches [] then num1 -> diff elseif num1 matches [] then mishap('Nums cannot subtract from zero', [^num1 ^num2]); else ;;; subtract an "x" from both and return the difference subnums(tail(num1), tail(num2)) -> diff endif else mishap('Nums needed for subnums', [^num1 ^num2]); endif; enddefine; ;;; Another version, subnums2 using the pattern matcher /* PROCEDURE: subnums2 (num1, num2) -> diff INPUTS : num1, num2 Where : num1 is a number num2 is a number OUTPUTS : diff is a number USED IN : ??? CREATED : 21 Jun 2009 PURPOSE : ??? if num1 is bigger than or equal to num2 then return a number which when added to num2 gives num1 TESTS: subnums2( [], [] ) => ** [] subnums2( [x], [] ) => ** [x] subnums2( [], [x] ) => ;;; MISHAP - Cannot subtract bigger number from smaller ;;; INVOLVING: [] [x] ;;; FILE : /home/axs/popd/nums.p LINE NUMBER: 174 ;;; DOING : subnums2 runproc subnums2( [x x x], [x] ) => ** [x x] subnums2( [x x x], [x x x x] ) => ;;; MISHAP - Cannot subtract bigger number from smaller ;;; INVOLVING: [x x x] [x x x x] ;;; FILE : /home/axs/popd/nums.p LINE NUMBER: 187 ;;; DOING : subnums2 runproc subnums2( [x x x x], [x x x x] ) => ** [] subnums2( [x x x x x x x x], [x x x x] ) => ** [x x x x] */ define subnums2(num1, num2) -> diff; if isnum(num1) and isnum(num2) then if num1 matches ![??diff ^^num2] then ;;; nothing else to do else mishap('Cannot subtract bigger number from smaller', [^num1 ^num2]) endif else mishap('Nums needed for subnums', [^num1 ^num2]); endif; enddefine; ;;; Multiplication as repeated addition /* PROCEDURE: mult (num1, num2) -> product INPUTS : num1, num2 Where : num1 is a num num2 is a num OUTPUTS : product is a num USED IN : ??? CREATED : 30 May 2009 PURPOSE : multiply two numbers (as lists) returning the product TESTS: mult([], []) => ** [] mult([], [x x x x]) => ** [] mult([x x x x], []) => ** [] mult([x x x x], [x]) => ** [x x x x] mult([x], [x x x x]) => ** [x x x x] mult([x x], [x x x x]) => ** [x x x x x x x x] */ define mult(num1, num2) -> product; if isnum(num1) and isnum(num2) then if num1 matches [] then [] -> product elseif num2 matches [] then [] -> product else [] -> product; until num2 matches [] do addnums(num1, product) -> product; tail(num2) -> num2; enduntil; endif else mishap('Nums needed for product', [^num1 ^num2]); endif; enddefine; define samenum(num1, num2) -> boole; (isnum(num1) and isnum(num2) and num1 matches num2) -> boole enddefine; /* PROCEDURE: bigger (num1, num2) -> boole INPUTS : num1, num2 Where : num1 is a num num2 is a num OUTPUTS : boole is a boolean USED IN : ??? CREATED : 30 May 2009 PURPOSE : determine whether num1 is bigger than num2 TESTS: bigger([], []) => ** bigger([x], []) => ** bigger([], [x]) => ** bigger([x x], [x x]) => ** bigger([x x x], [x x]) => ** bigger([x x x x x], [x x]) => ** bigger([x x], [x x x x]) => ** */ define bigger(num1, num2) -> boole; if samenum(num1, num2) then false -> boole elseif num1 matches [] then false -> boole elseif num2 matches [] then true -> boole else bigger(tail(num1), tail(num2)) -> boole endif enddefine; /* PROCEDURE: between (num1, num2, num3) -> boole INPUTS : num1, num2, num3 Where : num1 is a number num2 is a number num3 is a number OUTPUTS : boole is a boolean USED IN : ??? CREATED : 21 Jun 2009 PURPOSE : Check whether num1 is between num2 and num3 in ascending or descending order TESTS: between([x], [x], [x]) => ** between([x x], [x], []) => ** between([x], [x x], []) => ** between([x x], [x], [x x x]) => ** between([x x], [x x], [x x x]) => ** */ define between(num1, num2, num3) -> boole; (bigger(num3, num1) and bigger(num1, num2)) or (bigger(num2, num1) and bigger(num1, num3)) -> boole enddefine; /* PROCEDURE: divrem (num1, num2) -> (divider, remainder) INPUTS : num1, num2 Where : num1 is a number num2 is a number OUTPUTS : divider, remainder Where : divider is a number remainder is a number USED IN : ??? CREATED : 21 Jun 2009 PURPOSE : given two numbers num1, num2, divide num1 by num2 and return divider and remainder TESTS: divrem([], []) => ;;; MISHAP - Cannot divide [] into [] ;;; FILE : /home/axs/popd/nums.p LINE NUMBER: 327 ;;; DOING : divrem runproc divrem([], [x]) => ** [] [] divrem([x], [x]) => ** [x] [] divrem([x x x x], [x x]) => ** [x x] [] divrem([x x x x x x x], [x x x]) => ** [x x] [x] */ define divrem(num1, num2) -> (divider, remainder); if num2 == [] then mishap('Cannot divide [] into ' >< num1, []); elseif bigger(num2, num1) then [] -> divider; num1 -> remainder elseif samenum(num1, num2) then [x] -> divider; [] -> remainder else divrem(subnums(num1, num2), num2) -> (divider, remainder); addnums([x], divider) -> divider; endif; enddefine; /* false -> popsyscall */