多线程拼图

时间:2009-12-07 20:16:23

标签: multithreading parallel-processing puzzle

我正在努力想出一些专注于多线程的编程难题。到目前为止,我能够提出的大部分问题都是针对特定领域的。对于试图学习多线程应用程序核心概念的开发人员,是否有任何人有任何不错的编程难题?

12 个答案:

答案 0 :(得分:11)

此链接涵盖了许多主题。

Multithreaded Programming with ThreadMentor : A Tutorial

修改

以下是该链接中列出的问题的一些直接链接及其初始说明。

ThreadMentor : The Dining Philosopher's Problem
ThreadMentor : The Dining Philosopher's Problem: The Lefty-Righty Version

  

餐饮哲学家的问题是由E. W. Dijkstra发明的。想象一下,五个哲学家只是在思考和东方生活。餐厅中间是一张带五把椅子的圆桌。桌子上有一大盘意大利面。但是,只有五根筷子可用,如下图所示。每个哲学家都在想。当他饿了,他坐下来拿起最接近他的两根筷子。如果一个哲学家可以拿起两根筷子,他会吃一段时间。在一位哲学家吃完之后,他放下筷子开始思考。

ThreadMentor : The Cigarette Smoker's Problem

  

这个问题是由S. S. Patil于1971年引起的。假设一支香烟需要三种成分,烟草,纸和火柴。有三个连锁吸烟者。他们每个人只有一种无限供应的成分。有一种代理人可以无限供应所有三种成分。为了制作香烟,吸烟者必须使用另外两种成分纸和烟草(分别是烟草和火柴,以及烟草和纸)。代理人和吸烟者共用一张桌子。代理人随机生成两种成分,并通知需要这两种成分的吸烟者。一旦从桌子上取出配料,代理商再提供两个。另一方面,每个吸烟者等待代理人的通知。一旦通知,吸烟者拿起食材,抽一支烟,抽烟一会儿,然后回到餐桌旁等待下一份食材。

ThreadMentor : The Producer/Consumer (or Bounded-Buffer) Problem

  

假设我们有一个循环缓冲区,其中有两个指针输入和输出,用于指示存储数据的下一个可用位置以及包含要检索的下一个数据的位置。见下图。有两组线程,生产者和消费者。每个生产者将数据项存入就位并使指针前进,并且每个消费者将位置输出的数据项检索出来并使指针前进。

ThreadMentor : The Roller Coaster Problem

  

假设有n名乘客和一辆过山车。乘客反复等待乘坐可以容纳最多C乘客的汽车,其中C <1。 ñ。但是,只有当车满时,它才能绕过赛道。完成骑行后,每位乘客在游乐园周围游荡,然后返回过山车再骑一次。出于安全原因,该车只能骑行T次然后开枪。

这个有其他限制:

  1. 汽车总是乘坐C乘客;
  2. 汽车行驶时,没有乘客会从车上跳下来;
  3. 汽车行驶时,没有乘客会跳上车;
  4. 在下车之前,没有乘客会要求再次乘车。
  5. ThreadMentor : The Bridge Problem

    这个的描述依赖于图像。这是一个修改过的引用,删除了图像引用。

      

    考虑一个狭窄的桥梁,只允许同一方向的三辆车同时穿过。如果桥上有三辆车,任何进入的车辆必须等到桥梁畅通。

         

    当车辆驶离桥梁时,我们有两种情况需要考虑。案例1,桥上还有其他车辆;而案例2现有车辆是桥上的最后一辆。在第一种情况下,应允许一辆同一方向的新车继续行驶。

         

    案例2更复杂,有两个子句。在这种情况下,出口车辆是桥上的最后一辆车。如果有车辆在相反方向等待,则应允许其中一辆继续行驶。或者,如果没有车辆在相反方向等待,则让等待的车辆朝同一方向行驶。

答案 1 :(得分:6)

Dining Philosophers Problem,是我想到的第一个。

答案 2 :(得分:2)

内存中有一个大型树结构。许多线程需要搜索结构。有时,线程需要在结构中插入或移除某些东西。你如何控制对结构的访问,以便程序能够正确运行(没有两个线程会在改变结构的情况下相互踩踏)并且有效(没有线程在不必被线程时被阻塞)?

答案 3 :(得分:2)

答案 4 :(得分:1)

Dining philosophers就是一个......

unisex bathroom是另一个

答案 5 :(得分:1)

也许您可以使用测试和设置共享标志的简单问题或以某种顺序一致的方式访问某种列表资源?

答案 6 :(得分:1)

答案 7 :(得分:1)

这是我在本科学习期间完成多线程的first problem

答案 8 :(得分:1)

根据您对多线程的处理方式,这会有所不同。

你在银行里。客户平均每2分钟一次到达。平均每位客户在2分钟内获得服务。

哪种解决方案可以为客户提供服务?一个公共线,或每个出纳员一行?

您的选择是否足以保证对线路长度的限制?

答案:由于客户到达的马尔可夫属性和每个人的实际服务时间,该行永远不会知道界限。另外,让他们在一条公共线路上等待是一个好主意,尽管这还不足以克服无限的线路。

答案 9 :(得分:1)

Elevator Simulator很常见。

答案 10 :(得分:1)

这是PARLANSE中实现的并行N-puzzle解算器。该语言具有类似LISP的语法,但实际上更接近于C(标量,结构,指针,函数调用),但与C语言不同,它具有本地范围。秘密在于并行fork-grain运算符(|| ...),它并行执行所有操作数,以及PARLANSE使用异常来阻止父粒的能力。

这个求解器在我尝试过的所有4路和8路机器上提供线性加速。

(define Version `N-puzzle Solver V1.1~l
Copyright (C) 1998-2009 Semantic Designs; All Rights Reserved~l')

(define SolveParticularPuzzle ~t)
(define ManhattanHeuristic ~t) ; Manhattan is really fast
(define PrintTrace ~f)

(include `parmodule.par')

(define ScrambleCount 10000)

(define PuzzleSize `Length of side of N-puzzle' +4) ; at least 3!

(define PuzzleSizeMinus1 +3)

(define PuzzleArea `Area of puzzle (= (-- N))' +16) ; (= (* PuzzleSize PuzzleSize))

(define PuzzleAreaMinus1 +15)

(define BlankTile `Code for a blank tile' 0)

(define puzzlepieceT `Codes for nonblank tiles'
    (sort natural (range 1 PuzzleArea)))   

(define BoardPositionT integer) ; normally positive, but sometime we reach off the edge

(define ConfigurationT (array puzzlepieceT 0 PuzzleAreaMinus1))

(define HardPuzzle1 `Solution found of length 29:
         2 1 5 6 2 3 7 11 10 6 2 3 7 11 10 14 13 9 8
         12 13 9 5 1 2 6 5 1 0'
   (lambda (function ConfigurationT void)
  (make ConfigurationT 01 11 02 00
               04 06 09 05
               13 12 07 03
               08 14 10 15)
   )lambda
)define

(define HardPuzzle2 `Solution found of length 31:
         0 4 5 6 10 9 5 1 2 3 7 6 10 9 5 1
         2 3 7 6 5 1 2 6 1 0 14 13 9 5 4 0'
   (lambda (function ConfigurationT void)
  (make ConfigurationT 13 00 02 09
               04 05 06 01
               08 07 03 11
               12 14 10 15)
   )lambda
)define

(define HardPuzzle3 `Solution found of length 56:
        1 2 6 7 3 2 6 10 14 15 11 10 9 5
        4 8 12 13 9 10 6 5 1 0 4 8 12 13
        14 10 6 7 11 10 9 13 14 15 11 10
        6 5 4 8 9 10 6 5 1 0 4 8 9 5 4 0
        Total solution time in seconds: 18-24 (on 8 processor machine)'
   (lambda (function ConfigurationT void)
  (make ConfigurationT 00 09 10 08
               15 12 03 02
               01 11 13 14
               06 04 07 05)
   )lambda
)define

(define HardPuzzle4 `Solution found of length 50:
         4 5 1 0 4 8 12 13 9 5 1 0 4 5 6
         10 14 13 9 8 4 5 6 2 1 5 9 10 14
         13 12 8 9 10 11 15 14 13 9 10 11
         7 3 2 1 5 9 8 4 0
         Total solution time in seconds: 125 (on 8 processor machine)'
   (lambda (function ConfigurationT void)
  (make ConfigurationT 00 15 06 07
               12 03 08 11
               04 13 02 05
               01 14 09 10)
   )lambda
)define

(define HardPuzzle5
    `Solution found of length 68:
     3 7 11 10 6 2 3 7 6 5 9 8 4 5 1 0 4 5 9 13 14 15 11
     7 6 5 1 2 6 5 9 8 12 13 14 10 6 5 4 8 12 13 14 15 11
     10 9 5 1 0 4 8 12 13 9 5 4 8 9 13 14 15 11 7 3 2 1 0
     Total solution time in seconds: 2790 (on 8 processor machine)'
   (lambda (function ConfigurationT void)
  (make ConfigurationT 15 09 00 14
               10 11 12 08
               03 02 13 07
               01 06 05 04)
   )lambda
)define

(define ParticularPuzzleToSolve HardPuzzle5)

(define PrintConfiguration
   (action (procedure [Puzzle (reference ConfigurationT)])
  (do [position BoardPositionT] +0 PuzzleAreaMinus1 +1
      (;; (ifthenelse (<= Puzzle:position 9)
         (;; (PAR:PutConsoleCharacter "0")(PAR:PutConsoleNatural Puzzle:position) );;
         (PAR:PutConsoleNatural Puzzle:position)
       )ifthenelse
      (PAR:PutConsoleSpace)
      (ifthen (== (modulo (coerce natural position) (coerce natural PuzzleSize))
              (coerce natural PuzzleSizeMinus1)coerce )==
          (PAR:PutConsoleNewline)
      )ifthen
      );;
  )do
   )action
)define

(define Solved? `Determines if puzzle is solved.'
  (lambda (function boolean
        [board (reference ConfigurationT)]
      )function                           
  (value (;; `Fast check for completed':
         (ifthen (~= board:0 BlankTile)
             (return ~f)
         )ifthen
         (do [position BoardPositionT] PuzzleAreaMinus1 +1 -1
         (ifthen (~= board:position (coerce natural position))
             (return ~f)
         )ifthen
         )do
     );;
     ~t ; all pieces are in proper places
  )value
   )lambda
)define

(define ScoreT `Estimate of configuration distance from solution.
       Zero means configuration is a solution.'
   (sort natural (range 0 1000))) ; s/b (range 0 (* PuzzleArea PuzzleArea))

(define SolvedScore `The score of a goal position.' 0)
(define UnsolvableScore `An impossibly big score.' 12345678)

(define LowerBoundOnScore
   (lambda (function ScoreT [Puzzle (reference ConfigurationT)])
  (let (= [OutOfPlaceTiles ScoreT] 0)
     (value
    (compileifthenelse ManhattanHeuristic ; ~t for Out-of-place, ~f for Manhattan
       (do [Row BoardPositionT] PuzzleSizeMinus1 +0 -1
           (do [Column BoardPositionT] PuzzleSizeMinus1 +0 -1
           (local (;; (= [position integer] (+ (* Row PuzzleSize)
                                  Column))=
                  (= [tile puzzlepieceT] Puzzle:position)
              );;
              (ifthen (~= tile BlankTile) ; ignore BlankTile
             (+= OutOfPlaceTiles
                   (+ (magnitude (- Row (coerce integer (// tile (coerce natural PuzzleSize)))))
                  (magnitude (- Column (coerce integer (modulo tile (coerce natural PuzzleSize)))))
                   )+ ; add Manhattan distance of tile from tile goal
             )+=
              )ifthen
           )local
           )do ; Column   
       )do ; Row
       (do [position BoardPositionT] PuzzleAreaMinus1
                     +1  ; skipping zero effectively ignores BlankTile
                     +1
           (ifthen (~= Puzzle:position (coerce natural position))
               (+= OutOfPlaceTiles)
           )ifthen
       )do
    )compileifthenelse
    OutOfPlaceTiles ; the answer
     )value
  )let
   )lambda
)define

(recursive PathElementT
   (define PathElementT `A series of moves of the blank tile.'
       (structure [Move BoardPositionT]
          [Next (reference PathElementT)]
       )structure
   )define
)recursive

(define EmptyPath (void (reference PathElementT))void )define

(define ValuedPathT `A path and the score it acheives.'   
    (structure [Solved boolean]
           [Score ScoreT]
           [Path (reference PathElementT)])
)define

(define MakeMove `Applies a move to a configuration'
   (lambda (function ConfigurationT
         (structure [BlankTilePosition BoardPositionT]
                [NewBlankPosition BoardPositionT]
                [ConfigurationBeforeMove
                      (reference ConfigurationT)]
             )structure )function
 (let (= [ResultConfiguration ConfigurationT]
        (@ ConfigurationBeforeMove)  )=
      (value        
     (;;
         (compileifthen PrintTrace
        (;; (PAR:PutConsoleNatural BlankTilePosition)
            (PAR:PutConsoleNatural NewBlankPosition)
        );;
         )compileifthen
         (trust (== ConfigurationBeforeMove:BlankTilePosition
            BlankTile)) 
         (= ResultConfiguration:BlankTilePosition
        ConfigurationBeforeMove:NewBlankPosition)
         (= ResultConfiguration:NewBlankPosition BlankTile)
     );;
     ResultConfiguration
      )value                                  
 )let
   )lambda
)define

(define TopEdge? `Determines if a position is along top edge of puzzle.'
   (lambda (function boolean BoardPositionT)
   (< ? PuzzleSize)
   )lambda
)define

(define BottomEdge? `Determines if a position is along bottom edge of puzzle.'
   (lambda (function boolean BoardPositionT)
   (>= ? (- PuzzleArea PuzzleSize))
   )lambda
)define

(define LeftEdge? `Determines if a position is along left edge of puzzle.'
   (lambda (function boolean BoardPositionT)
   (== (modulo (coerce natural ?) (coerce natural PuzzleSize)) 0)==
   )lambda
)define

(define RightEdge? `Determines if a position is along right edge of puzzle.'
   (lambda (function boolean BoardPositionT)
   (== (modulo (coerce natural ?) (coerce natural PuzzleSize))modulo
       (coerce natural PuzzleSizeMinus1)coerce )==
   )lambda
)define

(define Solved! (exception (lambda (function string (reference ValuedPathT))
                   `N-puzzle solution is:~l'
               )lambda
        )exception
)define

[SerialPrint semaphore]

[MaxMoves natural]

(define Npuzzle
   (lambda (function ValuedPathT
        [BlankTilePosition BoardPositionT]
        [PreviousBlankTilePosition BoardPositionT]
        [Puzzle ConfigurationT]
        [MovesToHere natural]
       )function
)lambda 
)define

(define Npuzzle `Solves a puzzle and generates a sequence which is a solution.'
  (lambda (function ValuedPathT
        [BlankTilePosition BoardPositionT]
        [PreviousBlankTilePosition BoardPositionT]
        [Puzzle ConfigurationT]
        [MovesToHere natural]
      )function
 (ifthenelse (value (compileifthen PrintTrace
            (;; (PAR:PutConsole (. `In Npuzzle at depth '))
                (PAR:PutConsoleNatural MovesToHere) (PAR:PutConsoleNewline)
                (PrintConfiguration (. Puzzle))
            );;
            )compileifthen
            (Solved? (. Puzzle)))
   (make ValuedPathT ~t 0 EmptyPath)make ; the answer
   (let (|| [valuedpath1 ValuedPathT]
        [valuedpath2 ValuedPathT]
        [valuedpath3 ValuedPathT]
        [valuedpath4 ValuedPathT]
        [Best ValuedPathT]
        (= [EstimatedDistance natural]
           (+ MovesToHere (LowerBoundOnScore (. Puzzle)))+ )=
    )||
     (ifthenelse (value (compileifthen PrintTrace
                (;; (PAR:PutConsole (. `Inside LET EstimatedDistance= '))
                (PAR:PutConsoleNatural EstimatedDistance) (PAR:PutConsoleNewline)
                );;
            )compileifthen
            (> EstimatedDistance MaxMoves) )
    (make ValuedPathT ~f EstimatedDistance EmptyPath) ; don't explore any further
    (value 
       (;; (assert (& (<= +0 BlankTilePosition)
              (< BlankTilePosition PuzzleArea) )& )assert
; (PAR:PutConsole (. `Solve subpuzzles: blank @ '))(PAR:PutConsoleNatural BlankTilePosition)(PAR:PutConsoleNewline)

           (try `Solve subpuzzles':
          (|| ; replace this by (;; to see pure serial execution times
              `Fork Right':
              (local (|| (= [NewBlankTilePosition BoardPositionT]
                    (++ BlankTilePosition) )=
                 [ExtendedPath (reference PathElementT)]
                 )||
             (ifthenelse (value (;; ; (PAR:PutConsole (. `Fork Right~l'))
                        );;
                (&& (~= NewBlankTilePosition
                    PreviousBlankTilePosition )~=
                (~ (RightEdge? BlankTilePosition))~
                )&& )value
                (;; (= valuedpath1
                   (Npuzzle NewBlankTilePosition
                        BlankTilePosition
                        (MakeMove BlankTilePosition
                              NewBlankTilePosition
                              (. Puzzle) )MakeMove
                        (++ MovesToHere)
                   )Npuzzle )=
                (ifthen valuedpath1:Solved
                   (;; (+= valuedpath1:Score) ; since we added a move
                       (= ExtendedPath (new PathElementT))
                       (= (@ ExtendedPath) (make PathElementT NewBlankTilePosition valuedpath1:Path) )=
                       (= valuedpath1:Path ExtendedPath)
                       (raise Solved! (. valuedpath1))
                   );;
                )ifthen
                );;
                (= valuedpath1 (make ValuedPathT ~f UnsolvableScore EmptyPath))=
             )ifthenelse
              )local
              `Fork Left':
              (local (|| (= [NewBlankTilePosition BoardPositionT]
                    (-- BlankTilePosition) )=
                 [ExtendedPath (reference PathElementT)]
                 )||
             (ifthenelse (value (;; ; (PAR:PutConsole (. `Fork Left~l'))
                        );;
                (&& (~= NewBlankTilePosition
                    PreviousBlankTilePosition )~=
                (~ (LeftEdge? BlankTilePosition))~
                )&& )value
                (;; (= valuedpath2
                   (Npuzzle NewBlankTilePosition
                        BlankTilePosition
                        (MakeMove BlankTilePosition
                              NewBlankTilePosition
                              (. Puzzle) )MakeMove
                        (++ MovesToHere)
                   )Npuzzle )=
                (ifthen valuedpath2:Solved
                   (;; (+= valuedpath2:Score) ; since we added a move
                       (= ExtendedPath (new PathElementT))
                       (= (@ ExtendedPath) (make PathElementT NewBlankTilePosition valuedpath2:Path) )=
                       (= valuedpath2:Path ExtendedPath)
                       (raise Solved! (. valuedpath2))
                   );;
                )ifthen
                );;
                (= valuedpath2 (make ValuedPathT ~f UnsolvableScore EmptyPath))=
             )ifthenelse
              )local
              `Fork Down':
              (local (|| (= [NewBlankTilePosition BoardPositionT]
                    (- BlankTilePosition PuzzleSize) )=
                 [ExtendedPath (reference PathElementT)]
                 )||
             (ifthenelse (value (;; ; (PAR:PutConsole (. `Fork Down~l'))
                        );;
                (&& (~= NewBlankTilePosition
                    PreviousBlankTilePosition )~=
                (~ (TopEdge? BlankTilePosition))~
                )&& )value
                (;; (= valuedpath3
                   (Npuzzle NewBlankTilePosition
                        BlankTilePosition
                        (MakeMove BlankTilePosition
                              NewBlankTilePosition
                              (. Puzzle) )MakeMove
                        (++ MovesToHere)
                   )Npuzzle )=
                (ifthen valuedpath3:Solved
                   (;; (+= valuedpath3:Score) ; since we added a move
                       (= ExtendedPath (new PathElementT))
                       (= (@ ExtendedPath) (make PathElementT NewBlankTilePosition valuedpath3:Path) )=
                       (= valuedpath3:Path ExtendedPath)
                       (raise Solved! (. valuedpath3))
                   );;
                )ifthen
                );;
                (= valuedpath3 (make ValuedPathT ~f UnsolvableScore EmptyPath))=
             )ifthenelse
              )local
              `Fork Up':
              (local (|| (= [NewBlankTilePosition BoardPositionT]
                    (+ BlankTilePosition PuzzleSize) )=
                 [ExtendedPath (reference PathElementT)]
                 )||
             (ifthenelse (value (;; ; (PAR:PutConsole (. `Fork Up~l'))
                        );;
                (&& (~= NewBlankTilePosition
                    PreviousBlankTilePosition )~=
                (~ (BottomEdge? BlankTilePosition))~
                )&& )value
                (;; (= valuedpath4
                   (Npuzzle NewBlankTilePosition
                        BlankTilePosition
                        (MakeMove BlankTilePosition
                              NewBlankTilePosition
                              (. Puzzle) )MakeMove
                        (++ MovesToHere)
                   )Npuzzle )=
                (ifthen valuedpath4:Solved
                   (;; (+= valuedpath4:Score) ; since we added a move
                       (= ExtendedPath (new PathElementT))
                       (= (@ ExtendedPath) (make PathElementT NewBlankTilePosition valuedpath4:Path) )=
                       (= valuedpath4:Path ExtendedPath)
                       (raise Solved! (. valuedpath4))
                   );;
                )ifthen
                );;
                (= valuedpath4 (make ValuedPathT ~f UnsolvableScore EmptyPath))=
             )ifthenelse
              )local
          ) ; || or ;;
          `Exception handler':
          (;; ; (PAR:PutConsole (. `Exception handler~l'))
              (ifthenelse (== (exception) Solved!)==
             (;; (= Best (@ (exceptionargument (reference ValuedPathT))))=
                 (acknowledge (;; );; )acknowledge
             );;
             (propagate) ; oops, something unexpected!
              )ifthenelse
          );;
          `Success handler':
          (;; ; (PAR:PutConsole (. `Success (no exception raised)!~l'))
              `If we get here, no result is a solution,
               and all results have leaf-estimated scores.'
              (ifthenelse (< valuedpath1:Score valuedpath2:Score)
             (= Best valuedpath1)
             (= Best valuedpath2)
              )ifthenelse
              (ifthen (< valuedpath3:Score Best:Score)
                  (= Best valuedpath3) )ifthen
              (ifthen (< valuedpath4:Score Best:Score)
                  (= Best valuedpath4) )ifthen
         );;
        )try
     );;
     Best ; the answer to return
      )value
    )ifthenelse
  )let
)ifthenelse
  )lambda
)define

[StartTimeMicroseconds natural]
(define ElapsedTimeSeconds
   `Returns time in seconds rounded to nearest integer'
   (lambda (function natural void)
       (/ (- (+ (MicrosecondClock) 500000) StartTimeMicroseconds) 1000000)
   )lambda
)define

(define main
   (action (procedure void)
  (local (|| [PuzzleToSolve ConfigurationT]
         [BlankTilePosition BoardPositionT]
         [Solution ValuedPathT]
         [BlankLocation BoardPositionT]
         [Neighbor BoardPositionT]
         [PathScanP (reference PathElementT)]
         [ElapsedTime natural]
     )||
     (;; (PAR:PutConsoleString Version)
     (consume (addresource SerialPrint 1))
     `Set PuzzleToSolve to Solved position':
     (do [position BoardPositionT] +0 PuzzleAreaMinus1 +1
         (= PuzzleToSolve:position (coerce puzzlepieceT position) )=
     )do
     (ifthenelse SolveParticularPuzzle
        (;; (PAR:PutConsole (. `Hard puzzle...~l'))
        (= PuzzleToSolve (ParticularPuzzleToSolve) )= );;
        (;; `Scramble puzzle position'
        (PAR:PutConsole (. `Random puzzle...~l'))
        (= BlankLocation +0)
        (do [i natural] 1 (modulo (MicrosecondClock)
                      ScrambleCount)modulo 1
            (;; (= Neighbor BlankLocation)
            (ifthenelse (== (PAR:GetRandomNat 2) 0)
               (;; `Move Blank up or down'
                (ifthenelse (== (PAR:GetRandomNat 2) 0)
                   (ifthen (~ (TopEdge? BlankLocation)) (-= Neighbor PuzzleSize))
                   (ifthen (~ (BottomEdge? BlankLocation)) (+= Neighbor PuzzleSize))
                )ifthenelse
               );;
               (;; `Move Blank left or right'
                   (ifthenelse (== (PAR:GetRandomNat 2) 0)
                  (ifthen (~ (LeftEdge? BlankLocation)) (-= Neighbor))
                  (ifthen (~ (RightEdge? BlankLocation)) (+= Neighbor))
                   )ifthenelse
               );;
             )ifthenelse
             ; (PAR:PutConsoleNatural BlankLocation)(PAR:PutConsoleNatural Neighbor)(PAR:PutConsoleSpace)
             (ifthen (~= BlankLocation Neighbor)
                (= PuzzleToSolve
                   (MakeMove BlankLocation Neighbor (. PuzzleToSolve). )MakeMove )=
             )ifthen
             (= BlankLocation Neighbor)=
            );;
        )do
        );;
     )ifthenelse
     (;; `Initialize solver'
         (= Solution:Solved ~f)
         (= Solution:Score 0)
         (do FindBlankTile 
         [position BoardPositionT] +0 PuzzleAreaMinus1 +1
           (ifthen (== PuzzleToSolve:position BlankTile)
                       (;; (= BlankTilePosition position)
                           (exitblock FindBlankTile)
                           );; )ifthen )do
     );;
     (PAR:PutConsole (. `~lInitial Configuration:~l'))
     (PrintConfiguration (. PuzzleToSolve))
     (PAR:PutConsole (. `Estimate of solution length: '))
     (PAR:PutConsoleNatural (LowerBoundOnScore (. PuzzleToSolve)))
     (PAR:PutConsoleNewline)
     (= StartTimeMicroseconds (MicrosecondClock))
     (while (~ Solution:Solved)
         (;; (critical SerialPrint 1
            (;; (PAR:PutConsole (. `*** Iteration to depth '))
            (PAR:PutConsoleNatural Solution:Score)
            (PAR:PutConsole (. `    ')) (PAR:PutConsoleNatural (ElapsedTimeSeconds)) (PAR:PutConsole (. ` Seconds'))
            (PAR:PutConsoleNewline)
            );;
         )critical
         (= MaxMoves Solution:Score)
         (= Solution (Npuzzle BlankTilePosition BlankTilePosition PuzzleToSolve 0) )=
         );;
     )while
     (= ElapsedTime (ElapsedTimeSeconds))
     (critical SerialPrint 1
        (;; (PAR:PutConsole (. `Solution found of length '))
        (PAR:PutConsoleNatural Solution:Score) (PAR:PutConsole (. `: '))
        (iterate (= PathScanP Solution:Path)
             (~= PathScanP EmptyPath)
             (= PathScanP PathScanP:Next)
           (;; (PAR:PutConsoleNatural (coerce natural PathScanP:Move)) (PAR:PutConsoleSpace)
           );;
        )iterate
        (PAR:PutConsoleNewline)
        (PAR:PutConsole (. `Total solution time in seconds: '))  (PAR:PutConsoleNatural ElapsedTime) (PAR:PutConsoleNewline)
        );;
    )critical
     );;
  )local
   )action
)define

答案 11 :(得分:1)

The little book of semaphores这是免费提供的书有很多同步难题。它包括几乎所有其他答案中引用的谜题。为所有难题提供解决方案。