tasks a-s

This commit is contained in:
Ingy döt Net 2013-04-10 23:57:08 -07:00
parent 47bf37c096
commit b83f433714
12433 changed files with 156208 additions and 123 deletions

View file

@ -0,0 +1,12 @@
This puzzle involves a [http://xunor.free.fr/en/riddles/auto/pyramidnb.php Pascals Triangle], also known as a [http://xunor.free.fr/en/riddles/auto/pyramidnb.php Pyramid of Numbers].
<pre>
[ 151]
[ ][ ]
[40][ ][ ]
[ ][ ][ ][ ]
[ X][11][ Y][ 4][ Z]
</pre>
Each brick of the pyramid is the sum of the two bricks situated below it.<br>
Of the three missing numbers at the base of the pyramid, the middle one is the sum of the other two (that is, Y = X + Z).
Write a program to find a solution to this puzzle.

View file

@ -0,0 +1,96 @@
MODE
FIELD = REAL,
VEC = [0]REAL,
MAT = [0,0]REAL;
MODE BRICK = UNION(INT, CHAR);
FLEX[][]BRICK puzzle = (
( 151),
( " ", " "),
( 40, " ", " "),
( " ", " ", " ", " "),
( "x", 11, "y", 4, "z")
);
PROC mat col = (INT row, col)INT: row*(row-1)OVER 2 + col;
INT col x = mat col(5,1),
col y = mat col(5,3),
col z = mat col(5,5);
OP INIT = (REF VEC vec)VOID: FOR elem FROM LWB vec TO UPB vec DO vec[elem]:=0 OD;
OP INIT = (REF MAT mat)VOID: FOR row FROM LWB mat TO UPB mat DO INIT mat[row,] OD;
OP / = (MAT a, MAT b)MAT:( # matrix division #
[LWB b:UPB b]INT p ;
INT sign;
[,]FIELD lu = lu decomp(b, p, sign);
[LWB a:UPB a, 1 LWB a:2 UPB a]FIELD out;
FOR col FROM 2 LWB a TO 2 UPB a DO out[,col] := lu solve(b, lu, p, a[,col]) OD;
out
);
OP / = (VEC a, MAT b)VEC: ( # vector division #
[LWB a:UPB a,1]FIELD transpose a;
transpose a[,1]:=a;
(transpose a/b)[,LWB a]
);
INT upb mat = mat col(UPB puzzle, UPB puzzle);
[upb mat, upb mat] REAL mat; INIT mat;
[upb mat] REAL vec; INIT vec;
INT mat row := LWB mat;
INT known row := UPB mat - UPB puzzle + 1;
# build the simultaneous equation to solve #
FOR row FROM LWB puzzle TO UPB puzzle DO
FOR col FROM LWB puzzle[row] TO UPB puzzle[row] DO
IF row < UPB puzzle THEN
mat[mat row, mat col(row, col)] := 1;
mat[mat row, mat col(row+1, col)] := -1;
mat[mat row, mat col(row+1, col+1)] := -1;
mat row +:= 1
FI;
CASE puzzle[row][col] IN
(INT value):(
mat[known row, mat col(row, col)] := 1;
vec[known row] := value;
known row +:= 1
),
(CHAR variable):SKIP
ESAC
OD
OD;
# finally add x - y + z = 0 #
mat[known row, col x] := 1;
mat[known row, col y] := -1;
mat[known row, col z] := 1;
FORMAT real repr = $g(-5,2)$;
CO # print details of the simultaneous equation being solved #
FORMAT
vec repr = $"("n(2 UPB mat-1)(f(real repr)", ")f(real repr)")"$,
mat repr = $"("n(1 UPB mat-1)(f(vec repr)", "lx)f(vec repr)")"$;
printf(($"Vec: "l$,vec repr, vec, $l$));
printf(($"Mat: "l$,mat repr, mat, $l$));
END CO
# finally actually solve the equation #
VEC solution vec = vec/mat;
# and wrap up by printing the solution #
FLEX[UPB puzzle]FLEX[0]REAL solution;
FOR row FROM LWB puzzle TO UPB puzzle DO
solution[row] := LOC[row]REAL;
FOR col FROM LWB puzzle[row] TO UPB puzzle[row] DO
solution[row][col] := solution vec[mat col(row, col)]
OD;
printf(($n(UPB puzzle-row)(4x)$, $x"("f(real repr)")"$, solution[row], $l$))
OD;
FOR var FROM 1 BY 2 TO 5 DO
printf(($5x$,$g$,puzzle[UPB puzzle][var],"=", real repr, solution[UPB puzzle][var]))
OD

View file

@ -0,0 +1,69 @@
with Ada.Text_IO; use Ada.Text_IO;
procedure Pyramid_of_Numbers is
B_X, B_Y, B_Z : Integer := 0; -- Unknown variables
type Block_Value is record
Known : Integer := 0;
X, Y, Z : Integer := 0;
end record;
X : constant Block_Value := (0, 1, 0, 0);
Y : constant Block_Value := (0, 0, 1, 0);
Z : constant Block_Value := (0, 0, 0, 1);
procedure Add (L : in out Block_Value; R : Block_Value) is
begin -- Symbolically adds one block to another
L.Known := L.Known + R.Known;
L.X := L.X + R.X - R.Z; -- Z is excluded as n(Y - X - Z) = 0
L.Y := L.Y + R.Y + R.Z;
end Add;
procedure Add (L : in out Block_Value; R : Integer) is
begin -- Symbolically adds a value to the block
L.Known := L.Known + R;
end Add;
function Image (N : Block_Value) return String is
begin -- The block value, when X,Y,Z are known
return Integer'Image (N.Known + N.X * B_X + N.Y * B_Y + N.Z * B_Z);
end Image;
procedure Solve_2x2 (A11, A12, B1, A21, A22, B2 : Integer) is
begin -- Don't care about things, supposing an integer solution exists
if A22 = 0 then
B_X := B2 / A21;
B_Y := (B1 - A11*B_X) / A12;
else
B_X := (B1*A22 - B2*A12) / (A11*A22 - A21*A12);
B_Y := (B1 - A11*B_X) / A12;
end if;
B_Z := B_Y - B_X;
end Solve_2x2;
B : array (1..5, 1..5) of Block_Value; -- The lower triangle contains blocks
begin
-- The bottom blocks
Add (B(5,1),X); Add (B(5,2),11); Add (B(5,3),Y); Add (B(5,4),4); Add (B(5,5),Z);
-- Upward run
for Row in reverse 1..4 loop
for Column in 1..Row loop
Add (B (Row, Column), B (Row + 1, Column));
Add (B (Row, Column), B (Row + 1, Column + 1));
end loop;
end loop;
-- Now have known blocks 40=(3,1), 151=(1,1) and Y=X+Z to determine X,Y,Z
Solve_2x2
( B(1,1).X, B(1,1).Y, 151 - B(1,1).Known,
B(3,1).X, B(3,1).Y, 40 - B(3,1).Known
);
-- Print the results
for Row in 1..5 loop
New_Line;
for Column in 1..Row loop
Put (Image (B(Row,Column)));
end loop;
end loop;
end Pyramid_of_Numbers;

View file

@ -0,0 +1,4 @@
N1 := 11, N2 := 4, N3 := 40, N4 := 151
Z := (2*N4 - 7*N3 - 8*N2 + 6*N1) / 7
X := (N3 - 2*N1 - Z) / 2
MsgBox,, Pascal's Triangle, %X%`n%Z%

View file

@ -0,0 +1,274 @@
;---------------------------------------------------------------------------
; Pascal's triangle.ahk
; by wolf_II
;---------------------------------------------------------------------------
; http://rosettacode.org/wiki/Pascal's_triangle/Puzzle
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
AutoExecute: ; auto-execute section of the script
;---------------------------------------------------------------------------
#SingleInstance, Force ; only one instance allowed
#NoEnv ; don't check empty variables
;-----------------------------------------------------------------------
AppName := "Pascal's triangle"
N1 := 11, N2 := 4, N3 := 40, N4 := 151
; monitor MouseMove events
OnMessage(0x0200, "WM_MOUSEMOVE")
; GUI
Gosub, GuiCreate
Gui, Show,, %AppName%
Return
;---------------------------------------------------------------------------
GuiCreate: ; create the GUI
;---------------------------------------------------------------------------
Gui, -MinimizeBox
Gui, Margin, 8, 8
; 15 edit controls
Loop, 5
Loop, % Row := A_Index {
xx := 208 + (A_Index - 5) * 50 - (Row - 5) * 25
yy := 8 + (Row - 1) * 22
vv := Row "_" A_Index
Gui, Add, Edit, x%xx% y%yy% w50 v%vv% Center ReadOnly -TabStop
}
GuiControl, -WantReturn, Edit11
GuiControl, -WantReturn, Edit15
; buttons (2 hidden)
Gui, Add, Button, x8 w78, &Restart
Gui, Add, Button, x+8 wp, &Solve
Gui, Add, Button, x+8 wp, &Check
Gui, Add, Button, x8 wp, Cle&ar
Gui, Add, Button, xp wp Hidden, &Cancel
Gui, Add, Button, x+8 wp, &New
Gui, Add, Button, xp wp Hidden, &Apply
Gui, Add, Button, x+8 wp, E&xit
; status bar
Gui, Add, StatusBar
; blue font
Gui, Font, bold cBlue
GuiControl, Font, Edit11
GuiControl, Font, Edit15
; falling through
;---------------------------------------------------------------------------
ButtonRestart: ; restart retaining the blue clues
;---------------------------------------------------------------------------
Controls(True) ; enable controls
Loop, 15
If A_Index Not In 1,4,11,12,14,15
GuiControl,, Edit%A_Index% ; clear
GuiControl,, Edit1, %N4%
GuiControl,, Edit4, %N3%
GuiControl,, Edit12, %N1%
GuiControl,, Edit14, %N2%
GuiControl,, Edit11, %X%
GuiControl,, Edit15, %Z%
GreenFont:
Gui, Font, bold cGreen
GuiControl, Font, Edit1
GuiControl, Font, Edit4
GuiControl, Font, Edit12
GuiControl, Font, Edit14
Return
;---------------------------------------------------------------------------
ButtonSolve: ; calculate solution
;---------------------------------------------------------------------------
; N1 := 11 N2 := 4 N3 := 40 N4 := 151
;-----------------------------------------------------------------------
; Y = X + Z
; 40 = (11+X) + (11+Y)
; A = (11+Y) + (Y+4)
; B = (4+Y) + (4+Z)
; 151 = (40+A) + (A+B)
;-----------------------------------------------------------------------
Gosub, GreenFont
GuiControl,, Edit15, % Z := Round( (2*N4 - 7*N3 - 8*N2 + 6*N1) / 7 )
GuiControl,, Edit11, % X := Round( (N3 - 2*N1 - Z) / 2 )
; falling through
;---------------------------------------------------------------------------
ButtonCheck: ; check the [entry|solution] for errors
;---------------------------------------------------------------------------
Controls(False) ; disable controls
Gui, Submit, NoHide
X := 5_1, Z := 5_5
Loop, 5
Loop, % Row := A_Index
If (%Row%_%A_Index% = "")
%Row%_%A_Index% := 0
GuiControl,, Edit13, % 5_3 := 5_1 + 5_5
GuiControl,, Edit10, % 4_4 := 5_4 + 5_5
GuiControl,, Edit9, % 4_3 := 5_3 + 5_4
GuiControl,, Edit8, % 4_2 := 5_2 + 5_3
GuiControl,, Edit7, % 4_1 := 5_1 + 5_2
GuiControl,, Edit6, % 3_3 := 4_4 + 4_3
GuiControl,, Edit5, % 3_2 := 4_3 + 4_2
GuiControl,, Edit4, % 3_1 := 4_2 + 4_1
GuiControl,, Edit3, % 2_2 := 3_3 + 3_2
GuiControl,, Edit2, % 2_1 := 3_2 + 3_1
GuiControl,, Edit1, % 1_1 := 2_2 + 2_1
Gui, Font, bold cRed
If Not 3_1 = N3
GuiControl, Font, Edit4
If Not 1_1 = N4
GuiControl, Font, Edit1
Return
;---------------------------------------------------------------------------
ButtonClear: ; restart without the blue clues
;---------------------------------------------------------------------------
X := Z := ""
Gosub, ButtonRestart
Return
;---------------------------------------------------------------------------
ButtonNew: ; enter new numbers for the puzzle
;---------------------------------------------------------------------------
Gosub, GreenFont
Loop, 15
If A_Index Not In 1,4,12,14
GuiControl,, Edit%A_Index% ; clear
Controls(False) ; disable controls
NewContr(True) ; enable controls for new numbers
Return
;---------------------------------------------------------------------------
ButtonApply: ; remember the new numbers
;---------------------------------------------------------------------------
Gui, Submit, NoHide
N1 := 5_2, N2 := 5_4, N3 := 3_1, N4 := 1_1
NewContr(False) ; disable controls for new numbers
Controls(True) ; enable controls
Return
;---------------------------------------------------------------------------
ButtonCancel: ; restore the old numbers
;---------------------------------------------------------------------------
GuiControl,, Edit1, %N4%
GuiControl,, Edit4, %N3%
GuiControl,, Edit12, %N1%
GuiControl,, Edit14, %N2%
NewContr(False) ; disable controls for new numbers
Controls(True) ; enable controls
Return
;---------------------------------------------------------------------------
GuiClose:
;---------------------------------------------------------------------------
GuiEscape:
;---------------------------------------------------------------------------
ButtonExit:
;---------------------------------------------------------------------------
; common action
ExitApp
Return
;---------------------------------------------------------------------------
Controls(Bool) { ; [dis|re-en]able some controls
;---------------------------------------------------------------------------
Enable := Bool ? "+" : "-"
Disable := Bool ? "-" : "+"
GuiControl, %Disable%ReadOnly, Edit11
GuiControl, %Disable%ReadOnly, Edit15
GuiControl, %Enable%TabStop, Edit11
GuiControl, %Enable%TabStop, Edit15
GuiControl, %Disable%Default, &Restart
GuiControl, %Enable%Default, &Check
GuiControl, %Disable%Disabled, &Check
GuiControl, %Enable%Disabled, &Restart
}
;---------------------------------------------------------------------------
NewContr(Bool) { ; [dis|re-en]able control for new numbers
;---------------------------------------------------------------------------
Enable := Bool ? "+" : "-"
Disable := Bool ? "-" : "+"
GuiControl, %Disable%ReadOnly, Edit1
GuiControl, %Disable%ReadOnly, Edit4
GuiControl, %Disable%ReadOnly, Edit12
GuiControl, %Disable%ReadOnly, Edit14
GuiControl, %Enable%TabStop, Edit1
GuiControl, %Enable%TabStop, Edit4
GuiControl, %Enable%TabStop, Edit12
GuiControl, %Enable%TabStop, Edit14
GuiControl, %Enable%Hidden, Button1
GuiControl, %Enable%Hidden, Button2
GuiControl, %Enable%Hidden, Button3
GuiControl, %Enable%Hidden, Button4
GuiControl, %Disable%Hidden, Button5
GuiControl, %Enable%Hidden, Button6
GuiControl, %Disable%Hidden, Button7
GuiControl, %Enable%Hidden, Button8
}
;---------------------------------------------------------------------------
WM_MOUSEMOVE() { ; monitor MouseMove events
;---------------------------------------------------------------------------
; display quick help in StatusBar
;-----------------------------------------------------------------------
global AppName
CurrControl := A_GuiControl
IfEqual True,, MsgBox ; dummy
; mouse is over buttons
Else If (CurrControl = "&Restart")
SB_SetText("restart retaining the blue clues")
Else If (CurrControl = "&Solve")
SB_SetText("calculate solution")
Else If (CurrControl = "&Check")
SB_SetText("check if the entries are correct")
Else If (CurrControl = "Cle&ar")
SB_SetText("restart without the blue clues")
Else If (CurrControl = "&New")
SB_SetText("enter new numbers for the puzzle")
Else If (CurrControl = "E&xit")
SB_SetText("exit " AppName)
; delete status bar text
Else SB_SetText("")
}

View file

@ -0,0 +1,39 @@
INSTALL @lib$ + "ARRAYLIB"
REM Describe the puzzle as a set of simultaneous equations:
REM a + b = 151
REM a - c = 40
REM -b + c + d = 0
REM e + f = 40
REM -c + f + g = 0
REM -d + g + h = 0
REM e - x = 11
REM f - y = 11
REM g - y = 4
REM h - z = 4
REM x - y + z = 0
REM So we have 11 equations in 11 unknowns.
REM We can represent these equations as a matrix and a vector:
DIM matrix(10,10), vector(10)
matrix() = \ a, b, c, d, e, f, g, h, x, y, z
\ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
\ 1, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, \
\ 0,-1, 1, 1, 0, 0, 0, 0, 0, 0, 0, \
\ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, \
\ 0, 0,-1, 0, 0, 1, 1, 0, 0, 0, 0, \
\ 0, 0, 0,-1, 0, 0, 1, 1, 0, 0, 0, \
\ 0, 0, 0, 0, 1, 0, 0, 0,-1, 0, 0, \
\ 0, 0, 0, 0, 0, 1, 0, 0, 0,-1, 0, \
\ 0, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, \
\ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,-1, \
\ 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 1
vector() = 151, 40, 0, 40, 0, 0, 11, 11, 4, 4, 0
REM Now solve the simultaneous equations:
PROC_invert(matrix())
vector() = matrix().vector()
PRINT "X = " ; vector(8)
PRINT "Y = " ; vector(9)
PRINT "Z = " ; vector(10)

View file

@ -0,0 +1,39 @@
/* Pascal's pyramid solver
*
* [top]
* [ ] [ ]
* [mid] [ ] [ ]
* [ ] [ ] [ ] [ ]
* [ x ] [ a ] [ y ] [ b ] [ z ]
* x + z = y
*
* This solution makes use of a little bit of mathematical observation,
* such as the fact that top = 4(a+b) + 7(x+z) and mid = 2x + 2a + z.
*/
#include <stdio.h>
#include <math.h>
void pascal(int a, int b, int mid, int top, int* x, int* y, int* z)
{
double ytemp = (top - 4 * (a + b)) / 7.;
if(fmod(ytemp, 1.) >= 0.0001)
{
x = 0;
return;
}
*y = ytemp;
*x = mid - 2 * a - *y;
*z = *y - *x;
}
int main()
{
int a = 11, b = 4, mid = 40, top = 151;
int x, y, z;
pascal(a, b, mid, top, &x, &y, &z);
if(x != 0)
printf("x: %d, y: %d, z: %d\n", x, y, z);
else printf("No solution\n");
return 0;
}

View file

@ -0,0 +1,73 @@
#include <stdio.h>
#include <stdlib.h>
void show(int *x) {
int i, j;
for (i = 0; i < 5; i++)
for (j = 0; j <= i; j++)
printf("%4d%c", *(x++), j < i ? ' ' : '\n');
}
inline int sign(int i)
{
return i < 0 ? -1 : i > 0;
}
int iter(int *v, int *diff) {
int sum, i, j, e = 0;
# define E(x, row, col) x[(row) * ((row) + 1) / 2 + (col)]
/* enforce boundary conditions */
E(v, 0, 0) = 151;
E(v, 2, 0) = 40;
E(v, 4, 1) = 11;
E(v, 4, 3) = 4;
/* calculate difference from equilibrium */
for (i = 1; i < 5; i++) {
for (j = 0; j <= i; j++) {
E(diff, i, j) = 0;
if (j < i)
E(diff, i, j) += E(v, i - 1, j) -
E(v, i, j + 1) -
E(v, i, j);
if (j)
E(diff, i, j) += E(v, i - 1, j - 1) -
E(v, i, j - 1) -
E(v, i, j);
}
}
for (i = 0; i < 4; i++)
for (j = 0; j < i; j++)
E(diff, i, j) += E(v, i + 1, j) +
E(v, i + 1, j + 1) -
E(v, i, j);
E(diff, 4, 2) += E(v, 4, 0) + E(v, 4, 4) - E(v, 4, 2);
# undef E
/* Do feedback, check if we are done. */
for (i = sum = 0; i < 15; i++) {
sum += !!sign(e = diff[i]);
/* 1/5-ish feedback strength on average. These numbers are highly
magical, depending on nodes' connectivities. */
if (e >= 4 || e <= -4) v[i] += e/5;
else if (rand() < RAND_MAX/4) v[i] += sign(e);
}
return sum;
}
int main() {
int v[15] = { 0 }, diff[15] = { 0 }, i, s;
for (i = s = 1; s; i++) {
s = iter(v, diff);
printf("pass %d: %d\n", i, s);
}
show(v);
return 0;
}

View file

@ -0,0 +1,13 @@
pass 1: 12
pass 2: 12
pass 3: 14
pass 4: 14
...
pass 113: 4
pass 114: 7
pass 115: 0
151
81 70
40 41 29
16 24 17 12
5 11 13 4 8

View file

@ -0,0 +1,9 @@
(def bottom [ [0 1 0], [11 0 0], [0 1 1], [4 0 0], [0 0 1] ])
(defn plus [v1 v2] (vec (map + v1 v2)))
(defn minus [v1 v2] (vec (map - v1 v2)))
(defn scale [n v] (vec (map #(* n %) v )))
(defn above [row] (map #(apply plus %) (partition 2 1 row)))
(def rows (reverse (take 5 (iterate above bottom))))

View file

@ -0,0 +1,5 @@
(def c00 (get-in rows [0 0]))
(def c20 (get-in rows [2 0]))
(def eqn0 (minus c00 [151 0 0]))
(def eqn1 (minus c20 [ 40 0 0]))

View file

@ -0,0 +1,11 @@
(defn solve [m]
(assert (<= 1 m 2))
(let [n (- 3 m)
v0 (scale (eqn1 n) eqn0)
v1 (scale (eqn0 n) eqn1)
vd (minus v0 v1)]
(assert (zero? (vd n)))
(/ (- (vd 0)) (vd m))))
(let [x (solve 1), z (solve 2), y (+ x z)]
(println "x =" x ", y =" y ", z =" z))

View file

@ -0,0 +1,5 @@
(defn dot [v1 v2] (reduce + (map * v1 v2)))
(defn show-pyramid [x z]
(doseq [row rows]
(println (map #(dot [1 x z] %) row)))

View file

@ -0,0 +1,69 @@
import std.stdio, std.algorithm;
void iterate(bool doPrint=true)(double[] v, double[] diff) {
static ref T E(T)(T[] x, in size_t row, in size_t col)
pure nothrow {
return x[row * (row + 1) / 2 + col];
}
double sum = 0.0;
do {
// enforce boundary conditions
E(v, 0, 0) = 151;
E(v, 2, 0) = 40;
E(v, 4, 1) = 11;
E(v, 4, 3) = 4;
// calculate difference from equilibrium
foreach (i; 1 .. 5) {
foreach (j; 0 .. i + 1) {
E(diff, i, j) = 0;
if (j < i)
E(diff, i, j) += E(v, i - 1, j) -
E(v, i, j + 1) -
E(v, i, j);
if (j)
E(diff, i, j) += E(v, i - 1, j - 1) -
E(v, i, j - 1) -
E(v, i, j);
}
}
foreach (i; 1 .. 4)
foreach (j; 0 .. i)
E(diff, i, j) += E(v, i + 1, j) +
E(v, i + 1, j + 1) -
E(v, i, j);
E(diff, 4, 2) += E(v, 4, 0) + E(v, 4, 4) - E(v, 4, 2);
// do feedback, check if we are close enough
// 4: scale down the feedback to avoid oscillations
v[] += diff[] / 4;
sum = reduce!q{a + b ^^ 2}(0.0, diff);
static if (doPrint)
writeln("dev: ", sum);
// sum(dx^2) < 0.1 means each cell is no more than 0.5 away
// from equilibrium. It takes about 50 iterations. After
// 700 iterations sum is < 1e-25, but that's overkill.
} while (sum >= 0.1);
}
void main() {
static void show(in double[] x) {
int idx;
foreach (i; 0 .. 5)
foreach (j; 0 .. i+1) {
printf("%4d%c", cast(int)(0.5 + x[idx]),
j < i ? ' ' : '\n');
idx++;
}
}
double[15] v = 0.0;
double[15] diff = 0.0;
iterate(v, diff);
show(v);
}

View file

@ -0,0 +1,134 @@
package main
import "fmt"
// representation of an expression in x, y, and z
type expr struct {
x, y, z float64 // coefficients
c float64 // constant term
}
// add two expressions
func addExpr(a, b expr) expr {
return expr{a.x + b.x, a.y + b.y, a.z + b.z, a.c + b.c}
}
// subtract two expressions
func subExpr(a, b expr) expr {
return expr{a.x - b.x, a.y - b.y, a.z - b.z, a.c - b.c}
}
// multiply expression by a constant
func mulExpr(a expr, c float64) expr {
return expr{a.x * c, a.y * c, a.z * c, a.c * c}
}
// given a row of expressions, produce the next row up, by the given
// sum relation between blocks
func addRow(l []expr) []expr {
if len(l) == 0 {
panic("wrong")
}
r := make([]expr, len(l)-1)
for i := range r {
r[i] = addExpr(l[i], l[i+1])
}
return r
}
// given expression b in a variable, and expression a,
// take b == 0 and substitute to remove that variable from a.
func substX(a, b expr) expr {
if b.x == 0 {
panic("wrong")
}
return subExpr(a, mulExpr(b, a.x/b.x))
}
func substY(a, b expr) expr {
if b.y == 0 {
panic("wrong")
}
return subExpr(a, mulExpr(b, a.y/b.y))
}
func substZ(a, b expr) expr {
if b.z == 0 {
panic("wrong")
}
return subExpr(a, mulExpr(b, a.z/b.z))
}
// given an expression in a single variable, return value of that variable
func solveX(a expr) float64 {
if a.x == 0 || a.y != 0 || a.z != 0 {
panic("wrong")
}
return -a.c / a.x
}
func solveY(a expr) float64 {
if a.x != 0 || a.y == 0 || a.z != 0 {
panic("wrong")
}
return -a.c / a.y
}
func solveZ(a expr) float64 {
if a.x != 0 || a.y != 0 || a.z == 0 {
panic("wrong")
}
return -a.c / a.z
}
func main() {
// representation of given information for bottom row
r5 := []expr{{x: 1}, {c: 11}, {y: 1}, {c: 4}, {z: 1}}
fmt.Println("bottom row:", r5)
// given definition of brick sum relation
r4 := addRow(r5)
fmt.Println("next row up:", r4)
r3 := addRow(r4)
fmt.Println("middle row:", r3)
// given relation y = x + z
xyz := subExpr(expr{y: 1}, expr{x: 1, z: 1})
fmt.Println("xyz relation:", xyz)
// remove z from third cell using xyz relation
r3[2] = substZ(r3[2], xyz)
fmt.Println("middle row after substituting for z:", r3)
// given cell = 40,
b := expr{c: 40}
// this gives an xy relation
xy := subExpr(r3[0], b)
fmt.Println("xy relation:", xy)
// substitute 40 for cell
r3[0] = b
// remove x from third cell using xy relation
r3[2] = substX(r3[2], xy)
fmt.Println("middle row after substituting for x:", r3)
// continue applying brick sum relation to get top cell
r2 := addRow(r3)
fmt.Println("next row up:", r2)
r1 := addRow(r2)
fmt.Println("top row:", r1)
// given top cell = 151, we have an equation in y
y := subExpr(r1[0], expr{c: 151})
fmt.Println("y relation:", y)
// using xy relation, we get an equation in x
x := substY(xy, y)
fmt.Println("x relation:", x)
// using xyz relation, we get an equation in z
z := substX(substY(xyz, y), x)
fmt.Println("z relation:", z)
// show final answers
fmt.Println("x =", solveX(x))
fmt.Println("y =", solveY(y))
fmt.Println("z =", solveZ(z))
}

View file

@ -0,0 +1 @@
puzzle = [["151"],["",""],["40","",""],["","","",""],["X","11","Y","4","Z"]]

View file

@ -0,0 +1,29 @@
triangle n = n * (n+1) `div` 2
coeff xys x = maybe 0 id $ lookup x xys
row n cs = [coeff cs k | k <- [1..n]]
eqXYZ n = [(0, 1:(-1):1:replicate n 0)]
eqPyramid n h = do
a <- [1..h-1]
x <- [triangle (a-1) + 1 .. triangle a]
let y = x+a
return $ (0, 0:0:0:row n [(x,-1),(y,1),(y+1,1)])
eqConst n fields = do
(k,s) <- zip [1..] fields
guard $ not $ null s
return $ case s of
"X" - (0, 1:0:0:row n [(k,-1)])
"Y" - (0, 0:1:0:row n [(k,-1)])
"Z" - (0, 0:0:1:row n [(k,-1)])
_ - (fromInteger $ read s, 0:0:0:row n [(k,1)])
equations :: [[String]] - ([Rational], [[Rational]])
equations puzzle = unzip eqs where
fields = concat puzzle
eqs = eqXYZ n ++ eqPyramid n h ++ eqConst n fields
h = length puzzle
n = length fields

View file

@ -0,0 +1,10 @@
normalize :: [Rational] - [Integer]
normalize xs = [numerator (x * v) | x <- xs] where
v = fromInteger $ foldr1 lcm $ map denominator $ xs
run puzzle = map (normalize . drop 3) $ answer where
(a, m) = equations puzzle
lr = decompose 0 m
answer = case solve 0 lr a of
Nothing - []
Just x - x : kernel lr

View file

@ -0,0 +1,4 @@
*Main run puzzle
[[151,81,70,40,41,29,16,24,17,12,5,11,13,4,8]]
*Main run [[""],["2",""],["X","Y","Z"]]
[[3,2,1,1,1,0],[3,0,3,-1,1,2]]

View file

@ -0,0 +1 @@
chk=:40 151&-:@(2 4{{."1)

View file

@ -0,0 +1 @@
base=: [,11,+,4,]

View file

@ -0,0 +1 @@
ord=:5

View file

@ -0,0 +1 @@
|."2(#~chk"2) 2(+/\)^:(<ord)"1 base/"1>,{ ;~i:28

View file

@ -0,0 +1 @@
,.(1+i.5)<@{."0 1{.|."2(#~chk"2) 2(+/\)^:(<ord)"1 base/"1>,{ ;~i:28

View file

@ -0,0 +1 @@
,.(<@{."0 1~1+i.@#){.|."2(#~chk"2) 2(+/\)^:(<ord)"1 base/"1>,{ ;~i:28

View file

@ -0,0 +1,11 @@
b+c==a
d+e==b
e+f==c
g+h==d
h+i==e
i+j==f
l+X==g
l+Y==h
n+Y==i
n+Z==j
X+Z==Y

View file

@ -0,0 +1,4 @@
a->151
d->40
l->11
n->4

View file

@ -0,0 +1,3 @@
eqs={a==b+c,d+e==b,e+f==c,g+h==d,h+i==e,i+j==f,l+X==g,l+Y==h,n+Y==i,n+Z==j,Y==X+Z};
knowns={a->151,d->40,l->11,n->4};
Solve[eqs/.knowns,{b,c,e,f,g,h,i,j,X,Y,Z}]

View file

@ -0,0 +1 @@
{{b -> 81, c -> 70, e -> 41, f -> 29, g -> 16, h -> 24, i -> 17, j -> 12, X -> 5, Y -> 13, Z -> 8}}

View file

@ -0,0 +1,5 @@
151
81 70
40 41 29
16 24 17 12
5 11 13 4 8

View file

@ -0,0 +1,69 @@
%% to compile : ozc -x <file.oz>
functor
import
System Application FD Search
define
proc{Quest Root Rules}
proc{Limit Rc Ls}
case Ls of nil then skip
[] X|Xs then
{Limit Rc Xs}
case X of N#V then
Rc.N =: V
[] N1#N2#N3 then
Rc.N1 =: Rc.N2 + Rc.N3
end
end
end
proc {Pyramid R}
{FD.tuple solution 15 0#FD.sup R} %% non-negative integers domain
%% 01 , pyramid format
%% 02 03
%% 04 05 06
%% 07 08 09 10
%% 11 12 13 14 15
R.1 =: R.2 + R.3 %% constraints of Pyramid of numbers
R.2 =: R.4 + R.5
R.3 =: R.5 + R.6
R.4 =: R.7 + R.8
R.5 =: R.8 + R.9
R.6 =: R.9 + R.10
R.7 =: R.11 + R.12
R.8 =: R.12 + R.13
R.9 =: R.13 + R.14
R.10 =: R.14 + R.15
{Limit R Rules} %% additional constraints
{FD.distribute ff R}
end
in
{Search.base.one Pyramid Root} %% search for solution
end
local
Root R
in
{Quest Root [1#151 4#40 12#11 14#4 13#11#15]} %% supply additional constraint rules
if {Length Root} >= 1 then
R = Root.1
{For 1 15 1
proc{$ I}
if {Member I [1 3 6 10]} then
{System.printInfo R.I#'\n'}
else
{System.printInfo R.I#' '}
end
end
}
else
{System.showInfo 'No solution found.'}
end
end
{Application.exit 0}
end

View file

@ -0,0 +1,5 @@
Pascals_triangle_puzzle(topvalue=151,leftsidevalue=40,bottomvalue1=11,bottomvalue2=4) = {
y=(topvalue-(4*(bottomvalue1+bottomvalue2)))/7;
x=leftsidevalue-(y+2*bottomvalue1);
z=y-x;
print(x","y","z); }

View file

@ -0,0 +1,43 @@
(be number (@N @Max)
(@C box 0)
(repeat)
(or
((@ >= (val (-> @C)) (-> @Max)) T (fail))
((@N inc (-> @C))) ) )
(be + (@A @B @Sum)
(@ -> @A)
(@ -> @B)
(@Sum + (-> @A) (-> @B)) )
(be + (@A @B @Sum)
(@ -> @A)
(@ -> @Sum)
(@B - (-> @Sum) (-> @A))
T
(@ ge0 (-> @B)) )
(be + (@A @B @Sum)
(number @A @Sum)
(@B - (-> @Sum) (-> @A)) )
#{
151
A B
40 C D
E F G H
X 11 Y 4 Z
}#
(be puzzle (@X @Y @Z)
(+ @A @B 151)
(+ 40 @C @A)
(+ @C @D @B)
(+ @E @F 40)
(+ @F @G @C)
(+ @G @H @D)
(+ @X 11 @E)
(+ 11 @Y @F)
(+ @Y 4 @G)
(+ 4 @Z @H)
(+ @X @Z @Y) )

View file

@ -0,0 +1,19 @@
:- use_module(library(clpfd)).
puzzle(Ts, X, Y, Z) :-
Ts = [ [151],
[_, _],
[40, _, _],
[_, _, _, _],
[X, 11, Y, 4, Z]],
Y #= X + Z, triangle(Ts), append(Ts, Vs), Vs ins 0..sup, label(Vs).
triangle([T|Ts]) :- ( Ts = [N|_] -> triangle_(T, N), triangle(Ts) ; true ).
triangle_([], _).
triangle_([T|Ts], [A,B|Rest]) :- T #= A + B, triangle_(Ts, [B|Rest]).
% ?- puzzle(_,X,Y,Z).
% X = 5,
% Y = 13,
% Z = 8 ;

View file

@ -0,0 +1,31 @@
; Known;
; A.
; [ 151]
; [a ][b ]
; [40][c ][d ]
; [e ][f ][g ][h ]
; [ X][11][ Y][ 4][ Z]
;
; B.
; Y = X + Z
Procedure.i SolveForZ(x)
Protected a,b,c,d,e,f,g,h,z
For z=0 To 20
e=x+11: f=11+(x+z): g=(x+z)+4: h=4+z
If e+f=40
c=f+g : d=g+h: a=40+c: b=c+d
If a+b=151
ProcedureReturn z
EndIf
EndIf
Next z
ProcedureReturn -1
EndProcedure
Define x=-1, z=0, title$="Pascal's triangle/Puzzle in PureBasic"
Repeat
x+1
z=SolveForZ(x)
Until z>=0
MessageRequester(title$,"X="+Str(x)+#CRLF$+"Y="+Str(x+z)+#CRLF$+"Z="+Str(z))

View file

@ -0,0 +1,122 @@
# Pyramid solver
# [151]
# [ ] [ ]
# [ 40] [ ] [ ]
# [ ] [ ] [ ] [ ]
#[ X ] [ 11] [ Y ] [ 4 ] [ Z ]
# X -Y + Z = 0
def combine( snl, snr ):
cl = {}
if isinstance(snl, int):
cl['1'] = snl
elif isinstance(snl, string):
cl[snl] = 1
else:
cl.update( snl)
if isinstance(snr, int):
n = cl.get('1', 0)
cl['1'] = n + snr
elif isinstance(snr, string):
n = cl.get(snr, 0)
cl[snr] = n + 1
else:
for k,v in snr.items():
n = cl.get(k, 0)
cl[k] = n+v
return cl
def constrain(nsum, vn ):
nn = {}
nn.update(vn)
n = nn.get('1', 0)
nn['1'] = n - nsum
return nn
def makeMatrix( constraints ):
vmap = set()
for c in constraints:
vmap.update( c.keys())
vmap.remove('1')
nvars = len(vmap)
vmap = sorted(vmap) # sort here so output is in sorted order
mtx = []
for c in constraints:
row = []
for vv in vmap:
row.append(float(c.get(vv, 0)))
row.append(-float(c.get('1',0)))
mtx.append(row)
if len(constraints) == nvars:
print 'System appears solvable'
elif len(constraints) < nvars:
print 'System is not solvable - needs more constraints.'
return mtx, vmap
def SolvePyramid( vl, cnstr ):
vl.reverse()
constraints = [cnstr]
lvls = len(vl)
for lvln in range(1,lvls):
lvd = vl[lvln]
for k in range(lvls - lvln):
sn = lvd[k]
ll = vl[lvln-1]
vn = combine(ll[k], ll[k+1])
if sn is None:
lvd[k] = vn
else:
constraints.append(constrain( sn, vn ))
print 'Constraint Equations:'
for cstr in constraints:
fset = ('%d*%s'%(v,k) for k,v in cstr.items() )
print ' + '.join(fset), ' = 0'
mtx,vmap = makeMatrix(constraints)
MtxSolve(mtx)
d = len(vmap)
for j in range(d):
print vmap[j],'=', mtx[j][d]
def MtxSolve(mtx):
# Simple Matrix solver...
mDim = len(mtx) # dimension---
for j in range(mDim):
rw0= mtx[j]
f = 1.0/rw0[j]
for k in range(j, mDim+1):
rw0[k] *= f
for l in range(1+j,mDim):
rwl = mtx[l]
f = -rwl[j]
for k in range(j, mDim+1):
rwl[k] += f * rw0[k]
# backsolve part ---
for j1 in range(1,mDim):
j = mDim - j1
rw0= mtx[j]
for l in range(0, j):
rwl = mtx[l]
f = -rwl[j]
rwl[j] += f * rw0[j]
rwl[mDim] += f * rw0[mDim]
return mtx
p = [ [151], [None,None], [40,None,None], [None,None,None,None], ['X', 11, 'Y', 4, 'Z'] ]
addlConstraint = { 'X':1, 'Y':-1, 'Z':1, '1':0 }
SolvePyramid( p, addlConstraint)

View file

@ -0,0 +1,19 @@
from csp import Problem
p = Problem()
pvars = "R2 R3 R5 R6 R7 R8 R9 R10 X Y Z".split()
# 0-151 is the possible finite range of the variables
p.addvars(pvars, xrange(152))
p.addrule("R7 == X + 11")
p.addrule("R8 == Y + 11")
p.addrule("R9 == Y + 4")
p.addrule("R10 == Z + 4")
p.addrule("R7 + R8 == 40")
p.addrule("R5 == R8 + R9")
p.addrule("R6 == R9 + R10")
p.addrule("R2 == 40 + R5")
p.addrule("R3 == R5 + R6")
p.addrule("R2 + R3 == 151")
p.addrule("Y == X + Z")
for sol in p.xsolutions():
print [sol[k] for k in "XYZ"]

View file

@ -0,0 +1 @@
[5, 13, 8]

View file

@ -0,0 +1,33 @@
/*REXX program solves a "Pyramid of Numbers" puzzle given four values.*/
/*┌──────────────────────────────────────────────┐
answer
mid /
\ /
\ 151
\ ααα ααα
40 ααα ααα
ααα ααα ααα ααα
x 11 y 4 z
/ \
/ \
/ \
B D
*/
parse arg x b y d z mid answer . /*get some values, others, just X*/
pad=left('',15) /*for inserting spaces in output.*/
top=answer - 4*b - 4*d /*calculate the top # - constants*/
middle=mid - 2*b /*calculate the mod # - constants*/
do x =-top to top
do y=-top to top
if x+y\==middle then iterate /*40 = x+2B+Y -or- 40-2*11 =x+y*/
y6=y*6 /*calculate a short cut. */
do z=-top to top
if z\==y-x then iterate /*z has to equal y-x (y=x+z) */
if x+y6+z==top then say pad 'x = ' x pad "y = " y pad 'z = ' z
end /*z*/
end /*y*/
end /*x*/
/*stick a fork in it, we're done.*/

View file

@ -0,0 +1,59 @@
require 'rref'
pyramid = [
[ 151],
[nil,nil],
[40,nil,nil],
[nil,nil,nil,nil],
["x", 11,"y", 4,"z"]
]
p pyramid
equations = [[1,-1,1,0]] # y = x + z
def parse_equation(str)
eqn = [0] * 4
lhs, rhs = str.split("=")
eqn[3] = rhs.to_i
for term in lhs.split("+")
case term
when "x": eqn[0] += 1
when "y": eqn[1] += 1
when "z": eqn[2] += 1
else eqn[3] -= term.to_i
end
end
eqn
end
-2.downto(-5) do |row|
pyramid[row].each_index do |col|
val = pyramid[row][col]
sum = "%s+%s" % [pyramid[row+1][col].to_s, pyramid[row+1][col+1].to_s]
if val.nil?
pyramid[row][col] = sum
else
equations << parse_equation(sum + "=#{val}")
end
end
end
reduced = convert_to(reduced_row_echelon_form(equations), :to_i)
for eqn in reduced
if eqn[0] + eqn[1] + eqn[2] != 1
fail "no unique solution! #{equations.inspect} ==> #{reduced.inspect}"
elsif eqn[0] == 1: x = eqn[3]
elsif eqn[1] == 1: y = eqn[3]
elsif eqn[2] == 1: z = eqn[3]
end
end
puts "x == #{x}"
puts "y == #{y}"
puts "z == #{z}"
answer = []
for row in pyramid
answer << row.collect {|cell| eval cell.to_s}
end
p answer

View file

@ -0,0 +1,38 @@
program main;
class Triangle;
rand bit [7:0] a,b,c,d,e,f,g,h,X,Y,Z;
function new();
randomize;
$display(" [%0d]", 151);
$display(" [%0d][%0d]", a, b);
$display(" [%0d][%0d][%0d]", 40,c,d);
$display(" [%0d][%0d][%0d][%0d]", e,f,g,h);
$display(" [%0d][%0d][%0d][%0d][%0d]",X,11,Y,4,Z);
endfunction
constraint structure {
151 == a + b;
a == 40 + c;
b == c + d;
40 == e + f;
c == f + g;
d == g + h;
e == X + 11;
f == 11 + Y;
g == Y + 4;
h == 4 + Z;
};
constraint extra {
Y == X + Z;
};
endclass
Triangle answer = new;
endprogram

View file

@ -0,0 +1,68 @@
package require Tcl 8.5
namespace path ::tcl::mathop
set pyramid {
{151.0 "" "" "" ""}
{"" "" "" "" ""}
{40.0 "" "" "" ""}
{"" "" "" "" ""}
{x 11.0 y 4.0 z}
}
set equations {{1 -1 1 0}}
proc simplify {terms val} {
set vars {0 0 0}
set x 0
set y 1
set z 2
foreach term $terms {
switch -exact -- $term {
x - y - z {
lset vars [set $term] [+ 1 [lindex $vars [set $term]]]
}
default {
set val [- $val $term]
}
}
}
return [concat $vars $val]
}
for {set row [+ [llength $pyramid] -2]} {$row >= 0} {incr row -1} {
for {set cell 0} {$cell <= $row} {incr cell } {
set sum [concat [lindex $pyramid [+ 1 $row] $cell] [lindex $pyramid [+ 1 $row] [+ 1 $cell]]]
if {[set val [lindex $pyramid $row $cell]] ne ""} {
lappend equations [simplify $sum $val]
} else {
lset pyramid $row $cell $sum
}
}
}
set solution [toRREF $equations]
foreach row $solution {
lassign $row a b c d
if {$a + $b + $c > 1} {
error "problem does not have a unique solution"
}
if {$a} {set x $d}
if {$b} {set y $d}
if {$c} {set z $d}
}
puts "x=$x"
puts "y=$y"
puts "z=$z"
foreach row $pyramid {
set newrow {}
foreach cell $row {
if {$cell eq ""} {
lappend newrow ""
} else {
lappend newrow [expr [join [string map [list x $x y $y z $z] $cell] +]]
}
}
lappend solved $newrow
}
print_matrix $solved