Redigerer
Tårnet i Hanoi
(avsnitt)
Hopp til navigering
Hopp til søk
Advarsel:
Du er ikke innlogget. IP-adressen din vil bli vist offentlig om du redigerer. Hvis du
logger inn
eller
oppretter en konto
vil redigeringene dine tilskrives brukernavnet ditt, og du vil få flere andre fordeler.
Antispamsjekk.
Ikke
fyll inn dette feltet!
===Binære løsninger=== Skivenes posisjoner kan bestemmes av den [[binært tallsystem|binære]] (base 2) representasjonen av bevegelses-nummeret ''move'' (første tilstand er move #0, med alle sifre lik 0, og siste tilstand er #2<sup>''n''</sup>−1, med alle sifre lik 1), ved å bruke følgende regler: *Hver skive har et [[bit]] *Det mest signifikante bit representerer den største skiven. Verdien 0 indikerer at den største skiven er på start-pinnen, mens 1 indikerer at den er på den siste pinnen. *Bitstrengen leses fra venstre til høyre, og hvert bit kan brukes til å avgjøre posisjonen til den korresponderende skiven. *Et bit med samme verdi som det forutgående betyr at den korresponderende skiven ligger på toppen av den forrige skiven på samme pinne. **(En sekvens med bare 1'ere eller 0'ere betyr at alle korresponderende skiver er på samme pinne). *Et bit med en annen verdi enn den forrige betyr at den korresponderende skiven er i en posisjon til venstre eller høyre av den forrige. Hvorvidt det er venstre eller høyre avgjøres av følgende regel: **Forutsett at start-pinnen er til venstre og mål-pinnen er til høyre. **Forutsett også en ''wrapping'', slik at høyre pinne regnes som værende til «venstre» for venstre pinne, og omvendt. **La ''n'' være antall større skiver på samme pinne som deres første større skive, og adder 1 hvis den største skiven er på den venstre pinnen. Hvis ''n'' er et partall, befinner skiven seg en pinne til venstre. Hvis ''n'' er et oddetall, befinner skiven seg en pinne til høyre. Eksempel med et 8-skivers Hanoi-tårn: *Move #0) **Den største skiven er 0. Derfor befinner den seg på den venstre start-pinnen. **Alle andre skiver er også 0. Derfor ligger de i en stakk over den. Alle skivene er derfor på start-pinnen. *Move #2^8-1) **Den største skiven er 1, og er derfor på den høyre mål-pinnen. **Alle andre skiver er også 1. Derfor ligger de i en stakk over den. Alle skivene er derfor på mål-pinnen og puslespillet er fullført. *Move #0b11011000) **Den største skiven er 1, og er derfor på den høyre mål-pinnen. **Skive 2 er også 1, og ligger derfor over den største skiven på den høyre pinnen. **Skive 3 er 0, og er derfor på en annen pinne. Fordi ''n'' er et oddetall, er den en pinne til høyre, dvs. på venstre pinne. **Skive 4 er 1, og er derfor på en annen pinne. Fordi ''n'' fortsatt er et partall, er den en pinne til venstre, dvs. på høyre pinne. **Skive 5 er også 1, og ligger derfor på toppen av den, på høyre pinne. **Skive 6 er 0, og er derfor på en annen pinne. Fordi ''n'' fortsatt er et partall, er skiven en pinne til venstre, dvs. på den midterste pinnen. **Skivene 7 og 8 er også 0, og ligger derfor på toppen av den, på den midterste pinnen. Algoritmen ovenfor kan skrives slik i programmeringsspråket [[Scheme]]: <syntaxhighlight lang="scheme"> (define (conf m h f t) ; m=move number, h=høyde på tårnet, f=start-pinne, t=mål-pinne ; Identifiser pinnene med tallene 0, 1 og 2. (let loop ((prev-zero? #t) (mask (arithmetic-shift 1 (sub1 h))) (rotation (- t f)) (f f)) (if (zero? mask) () (let ((zero-bit? (zero? (bitwise-and mask m))) (mask (arithmetic-shift mask -1))) (if (eq? prev-zero? zero-bit?) (cons f (loop zero-bit? mask (- rotation) f)) (let ((f (modulo (+ f rotation) 3))) (cons f (loop zero-bit? mask rotation f)))))))) </syntaxhighlight> Prosedyren produserer en liste over posisjonene til skivene ordnet etter en stadig mindre størrelse. Eksempel: <syntaxhighlight lang="scheme"> > (conf #e6022e20 80 0 2) (01111111100001201201221111201112012000) </syntaxhighlight> Kilde- og målpinnene for forflytning nr ''m'' kan også bli funnet gjennom en binær representasjon av ''m'' ved å bruke [[bitvis operasjon|bitvise operasjoner]]. I syntaksen til [[C (programmeringsspråk)|programmeringspråket C]] er forflytning nr ''m'' fra pinne (m&m-1)%3 til pinne ((m|m-1)+1)%3, der hvor skivene starter på pinne 0 og avsluttes på pinne 1 eller 2, avhengig av om antall skiver er et partall eller oddetall. Skiven som flyttes identifiseres av antall ganger telleren ''m'' kan divideres med 2 (antall 0-bits til høyre), ved å telle første flytting som 1 og å nummerere skivene med tallene 0, 1, 2 etc etter stigende størrelse. Dette er en svært rask ikke-rekursiv algoritme for å finne skivenes posisjoner etter ''m'' forflytninger uten referanse til tidligere forflytninger eller skivenes fordeling: <syntaxhighlight lang="scheme"> ; h : det totale antall skiver ; m : flytter telleren, som begynner med 1 for første forflytning ; f : start-pinne; pinnene er nummererte 0, 1 og 2. ; t : mål-pinne ; d : skive (nummererte 0, 1, 2, etc ordnet etter økende størrelse) ; Funksjonen =quotient= tar to heltall og beregner deres kvosient avrundet til heltallet som er nærmest null. ; (rot3 m) : rotasjon av den gjenværende tredje pinne under flytting m. ; (rotd d) : rotasjon av skive d. ; mcnt : antallet flyttinger av skive d etter totalt m flyttinger. ; from : pinnen en skive hentes fra under flytting m. ; onto : pinnen en skive legges på under flytting m. ; thrd : den tredje pinnen. (- 3 fra onto) ; disk : skiven som flyttes. ; conf : posisjonen til skive d etter totalt m flyttinger. (define (exp2 n ) (expt 2 n)) (define (mod2 n ) (modulo n 2)) (define (mod3 n ) (modulo n 3)) (define (pari n ) (add1 (mod2 (add1 n)))) (define (rotd h d f t) (mod3 (* (- t f) (pari (- h d))))) (define (rot3 h f t) (rotd h 0 f t)) (define (mcnt m d ) (quotient (+ m (exp2 d)) (exp2 (add1 d)))) (define (thrd m h f t) (mod3 (- f (* m (rot3 h f t))))) (define (onto m h f t) (mod3 (- (thrd m h f t) (rotd h (disk m) f t)))) (define (from m h f t) (mod3 (+ (thrd m h f t) (rotd h (disk m) f t)))) (define (conf m h d f t) (mod3 (+ f (* (rotd h d f t) (mcnt m d))))) (define (disk m ) (sub1 (bit-count (bitwise-xor m (sub1 m))))) </syntaxhighlight>
Redigeringsforklaring:
Merk at alle bidrag til Wikisida.no anses som frigitt under Creative Commons Navngivelse-DelPåSammeVilkår (se
Wikisida.no:Opphavsrett
for detaljer). Om du ikke vil at ditt materiale skal kunne redigeres og distribueres fritt må du ikke lagre det her.
Du lover oss også at du har skrevet teksten selv, eller kopiert den fra en kilde i offentlig eie eller en annen fri ressurs.
Ikke lagre opphavsrettsbeskyttet materiale uten tillatelse!
Avbryt
Redigeringshjelp
(åpnes i et nytt vindu)
Navigasjonsmeny
Personlige verktøy
Ikke logget inn
Brukerdiskusjon
Bidrag
Opprett konto
Logg inn
Navnerom
Side
Diskusjon
norsk bokmål
Visninger
Les
Rediger
Rediger kilde
Vis historikk
Mer
Navigasjon
Forside
Siste endringer
Tilfeldig side
Hjelp til MediaWiki
Verktøy
Lenker hit
Relaterte endringer
Spesialsider
Sideinformasjon