unit Unit1;
logigram puzzel oplossing
--------------------------------
logigram:
---------------------------------------------------------------------------
5 personen: Mary, Wim, Peter, Anne en Corry,
5 opdrachten: huiswerk, examen, proefwerk, tentamen en overhoring
5 vakken: taal, rekenen, aardrijkskunde, geschiedenis en biologie
5 cijfers: 3,5,6,7 en 9
De voorwaarden zijn:
1) De persoon die het tentamen maakte, kreeg een hoger cijfer
dan degene die moest rekenen, maar een lager cijfer dan Corry.
2) Peter is niet degene die huiswerk moest maken. Hij heeft echter
een hoger cijfer dan Anne, maar een lager cijfer dan degene die
geschiedenis deed. We weten ook dat Peter geen 4 en ook geen 6 punten
meer kreeg dan de persoon die examen deed.
3) De leerlinge die het proefwerk maakte, kreeg een hoger cijfer
dan Mary die geen taal deed, maar een lager cijfer dan degene
die biologie deed.
4) Wim deed aardrijkskunde en kreeg een hoger cijfer dan degene
die taal deed. Hij kreeg echter een lager cijfer dan de persoon
die een overhoring had.
----------------------------------------------------------------------------
Welke opdracht, vak, cijfer hoort bij wie?
Dit programma berekent oplossingen.
Uitgangspunt is deze tabel:
--------------------------------------------------------
| kolom |
--------------------------------------------------------
0 1 2 3 |
persoon | opdracht | vak | cijfer |
--------------------------------------------------------
0 mary huiswerk taal 3 |
1 wim examen rekenen 5 |
2 peter proefwerk aardrijkskunde 6 |
3 anne tentamen geschiedenis 7 |
4 corrie overhoring biologie 9 |
--------------------------------------------------------
Bij het zoekem maar oplossingen blijven de personen in kolom 0
op hun plaats staan.
De rijen in kolommen 1 t/m 3 verwisselen echter, tot een combinatie
is gevonden zonder conflicten.
De opdrachten, vakken, personen en cijfers worden in het programma
aangeduid met hun rij in de tabel hierboven, dus als 0,1,2,3 of 4.
Omdat de personen niet van plaats wisselen, vormen die tevens het
nummer van een rij.
Per kolom zijn er 5! = 120 volgorden van de opdrachten,vakken of cijfers.
Een volgorde wordt met een getal van 0..119 aangegeven.
Er zijn dus 3 van die getallen nodig, ze staan in array permNr[1..3].
(permNr staat voor permutatie nummer)
PermNr[2] geeft de permutatie aan van kolom 2, bijvoorbeeld: 2,0,4,3,1
In de tabel hierboven is van elke kolom permutatie 0 weergegeven.
De getallen permutNr[1], permutNr[2] en permutNr[3] vormen een telwerk.
Elke teller telt van 0..119, bij 120 gaat de teller over de kop naar 0
en verhoogt de volgende teller.
PermutNr[1] van 120 naar 0 verhoogt PermuNr[2], enzovoorts.
Zo worden alle tellerstanden systematisch doorlopen.
Bij elke stand 0..119 hoort een volgorde van de elementen
in een kolom.
De omzetting van tellerstand naar permutatie (volgorde) gaat zo:
(stel dat we permutatie nummer 88 willen berekenen)
maak eerst permutatie 0 , dat is 0 1 2 3 4
deel 88 door 24 = 3 (88 div 24 = 3) opm. 24 = 4!
pak het 3e element uit de rij, dat is de -3-
de rest bij deling van 88 door 24 = 16 (88 mod 24 = 16)
haal de 3 weg uit de rij, dat levert de nieuwe rij 0 1 2 4 x
deel 16 door 6 , 16 div 6 = 2
neem het 2e element uit de rij, dat is de -2-
16 mod 6 = 4 opm. 6 = 3!
haal de 2 weg uit de rij, dat levert 0 1 4 x x
4 div 2 = 2
neem 2e getal uit de rij, dat is de -4-
4 mod 2 = 0
haal de 4 weg uit de rij, dat levert 0 1 x x x
0 div 1 = 0
neem 0e getal uit de rij, dat is de -0-
de nieuwe rij wordt 1 x x x x
pak nu het overgebleven getal, de -1-
De volgorde nummer 88 is dus 3 2 4 0 1
Wordt deze volgorde toegepast op de kolom "opdracht" dan wordt die kolom:
tentamen
examen
overhoring
huiswerk
examen
Maar de volgorde kan natuurlijk ook op andere kolommen slaan.
Dat achtereenvolgens wordt gedeeld door 24, 6, 3 en 1 zit zo:
er zijn 24 permutaties van 4 elementen. Deze kunnen als modulo 24
teller worden beschouwd.
Bij de eerste 24 permutaties zal de -0- voorop staan.
Bij permutaties 24..47 zal de 1 voorop staan. Enzovoort.
getal div 24 bepaalt dus het meest linkse element.
We verwijderen dit cijfer uit de rij 0 1 2 3 4, want het mag niet
opnieuw worden gekozen.
getal mod 24 is de rest bij deling en met dit getal gaan we verder.
Er zijn nu nog 4 cijfers te bepalen.
De laagste 3 vormen een modulo 3! = 6 teller zodat het hoogste cijfer
wordt bepaald door rest div 6.
En rest = rest mod 6 is wat overblijft.
Elk gevonden getal verwijderen we uit de rij.
Tenslotte wordt het laatste, overgebleven, getal aan de volgorde toegevoegd.
Om niet steeds dezelfde permutaties te hoeven berekenen wordt de tabel
permuts[0..4,0..119] bij het starten van het programma gevuld.
Die tabel bevat dus 120 rijtjes met alle permutaties van de cijfers 0..4
}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls, Buttons, shellapi, ExtCtrls;
type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
StaticText1: TStaticText;
StringGrid1: TStringGrid;
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure Image1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type Tstring5 = array[0..4] of string;
Tactivity = record
rij : byte; //plaats in de tabel hierboven
kolom : byte;
end;
const Spersonen : Tstring5 = //inhoud van de velden in tabel
('mary','wim','peter','anne','corrie');
Svakken : Tstring5 =
('taal','rekenen','aardrijkskunde','geschiedenis','biologie');
Sopdrachten : Tstring5 =
('huiswerk','examen','proefwerk','tentamen','overhoring');
Scijfers : Tstring5 =
('3','5','6','7','9');
huiswerk : Tactivity = (rij:0; kolom:1); //plaats in de tabel
examen : Tactivity = (rij:1; kolom:1);
proefwerk : Tactivity = (rij:2; kolom:1);
tentamen : Tactivity = (rij:3; kolom:1);
overhoring : Tactivity = (rij:4; kolom:1);
taal : Tactivity = (rij:0; kolom:2);
rekenen : Tactivity = (rij:1; kolom:2);
aardrijkskunde: Tactivity = (rij:2; kolom:2);
geschiedenis : Tactivity = (rij:3; kolom:2);
biologie : Tactivity = (rij:4; kolom:2);
mary = 0; //plaats in de kolom
wim = 1;
peter = 2;
anne = 3;
corrie = 4;
var permutNr : array[1..3] of byte; //hold permutation-index of columns
permuts : array[0..4,0..119] of byte;
getal : byte = 0; //alleen voor testen van permutaties
opl : byte; //nummer van de oplossing
procedure makepermuts;
//maak alle permutaties in array permuts[0..4,0..119]
const delers : array[0..3] of byte = (24,6,2,1);
var i,j,k,rest,quot : byte;
pel : array[0..4] of byte; //pel : permutatie van elementen 01234
begin
for j := 0 to 119 do
begin
for i := 0 to 4 do pel[i] := i;//set permutatie 0 = 01234
rest := j;
for i := 0 to 3 do
begin //maak permutatie j
quot := rest div delers[i];
rest:= rest mod delers[i];
permuts[i,j] := pel[quot];
for k := quot to 3 do pel[k] := pel[k+1]; //shift elements down
pel[4] := 0;
end;
permuts[4,j] := pel[0];//overblijvende getal
end;//for j
end;
procedure setCells;
//vul de tabel volgens permtNr[1..3]
var i,j,k : byte;
begin
k := 0;
with form1.stringgrid1 do
for i := 0 to 3 do //kolommen
begin
if i <> 0 then k := permutNr[i];
for j := 0 to 4 do //rijen
case i of
0 : cells[i,j] := Spersonen[j];
1 : cells[i,j] := Sopdrachten[permuts[j,k]];
2 : cells[i,j] := Svakken[permuts[j,k]];
3 : cells[i,j] := Scijfers[permuts[j,k]];
end;//case
end;
end;
procedure setBeginstand;
var i : byte;
begin
for i := 1 to 3 do permutNr[i] := 0;
setCells;
form1.statictext1.caption := 'beginstand';
opl := 0;
end;
function cijfer(n : byte) : byte;
//n: 0..4
//bepaal cijfer in rij n
var k : byte;
begin
k := permuts[n,permutNr[3]];
result := strtoint(Scijfers[k]);
end;
function persoon(a : Tactivity) : byte;
//bepaal persoon van activiteit a
var i,kolom,rij,k : byte;
begin
result := 0;
kolom := a.kolom;
rij := a.rij;
//--zoek rij nr in kolom
k := permutNr[kolom];
for i := 0 to 4 do
if permuts[i,k] = rij then result := i
end;
function checkOK : boolean;
//test of aan voorwaarden is voldaan
begin
result := (cijfer(persoon(tentamen)) > cijfer(persoon(rekenen))) and //1a
(cijfer(persoon(tentamen)) < cijfer(corrie)) and //1b
(persoon(rekenen) <> corrie) and //1c
(persoon(huiswerk) <> peter) and //2a
(cijfer(peter) > cijfer(anne)) and //2b
(persoon(examen) <> peter) and //2c
(cijfer(peter) < cijfer(persoon(geschiedenis))) and //2d
(cijfer(peter) <> cijfer(persoon(examen)) + 6) and //2e
(cijfer(peter) <> cijfer(persoon(examen)) + 4) and //2f
(cijfer(persoon(examen)) + 6 <= 9) and //2g
(cijfer(persoon(proefwerk)) > cijfer(mary)) and //3a
(persoon(taal) <> mary) and //3b
(cijfer(persoon(proefwerk)) < cijfer(persoon(biologie))) and//3c
(persoon(proefwerk)<>wim) and (persoon(proefwerk)<>peter) and //3d
(wim = persoon(aardrijkskunde)) and //4a
(cijfer(wim) > cijfer(persoon(taal))) and //4b
(cijfer(wim) < cijfer(persoon(overhoring))) //4c
end;
procedure TForm1.FormCreate(Sender: TObject);
//delphi roept deze procedure aan bij opstarten
begin
makepermuts;
SetBeginstand;
end;
function Increment : boolean;
//verhoog de teller permutNr[1..3]
//carry = overdracht, verhogen volgende positie
var carry : boolean;
i : byte;
begin
carry := true;
for i := 1 to 3 do
begin
if carry then inc(permutNr[i]);
if permutNr[i] = 120 then permutNr[i] := 0
else carry := false;
end;//for
result := carry;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
//aanroep bij klikken op knop "oplossen"
//zoeken naar oplossingen
begin;
statictext1.caption := 'computer zoekt...';
repeat
if checkOK then
begin
inc(opl);
statictext1.caption := 'oplossing gevonden'+' : '+inttostr(opl);
setCells;
increment;
exit;
end;
until increment;//until overflow
statictext1.caption := 'einde';
setbeginstand;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
//aanroep bij klokken op knop "beginstand"
begin
setbeginstand;
end;
procedure TForm1.Image1Click(Sender: TObject);
//davdata website link
begin
ShellExecute(0,'open','http://www.davdata.nl', nil, nil, SW_SHOWNORMAL);
end;
end.