Exemplo n.º 1
0
// run the algo, print some output and catch if won.
// straightAhead: true: new direction are initialized with current dir, false: init with 0
func Run(e engine.Engine, single bool, outputFreq int32, printSurface bool, straightAhead bool, threads int) {
	steps, solutions, solSteps = 0, 0, []int32{}
	numWorkers = 0
	running = true
	cDone = make(chan int8, threads) // queue for threads
	cHistory = make(chan bool, 1)    // mutex on global history object

	// preprocessing
	MarkDeadFields(&e.Surface)
	e.Print()

	// init time counter
	syscall.Gettimeofday(&starttime)

	// ???
	//	runtime.GOMAXPROCS(runtime.NumCPU())

	// init path
	path := Path{}
	path.Push(engine.NO_DIRECTION)

	// create history store and save initial constellation
	history = newHistoryTree(-1, -1)
	newHist := e.GetBoxesAndX()
	addHistory(&history, newHist)

	// prepare for starting workers
	wg.Add(1)
	cDone <- 1
	go runWorker(e, path, threads, single, outputFreq, printSurface, straightAhead)

	// wait for all workers to finish
	wg.Wait()
	//	time.Sleep(1 * time.Second)

	// print result
	min, sec, µsec := getTimePassed(starttime)
	log.A("Run finished with %d steps after %dm %ds %dµs.\n%d solutions found at following steps:\n%d\n", steps, min, sec, µsec, solutions, solSteps)
}
Exemplo n.º 2
0
func runWorker(e engine.Engine, basePath Path, threads int, single bool, outputFreq int32, printSurface bool, straightAhead bool) {
	// make sure, process will wait for this worker
	defer wg.Done()
	gorNo := numWorkers
	numWorkers++
	log.I(gorNo, "runWorker %d created, %d running", gorNo, runtime.NumGoroutine())
	e.Id = gorNo
	//	path := Path{basePath[len(basePath)-1].Clone()}
	path := basePath[len(basePath)-1:]

	basePath = basePath[:len(basePath)-1]
	//	basePath = basePath.Clone()

	//	log.I(gorNo, "path: %d, basePath: %d", path, basePath)

	for {
		var ignoredDir = false
		ignoredDir = false
		// ### 1. check if finished
		if path.Empty() || !running {
			log.D(e.Id, "Empty path / stopped executition. Hopefully all possibilities tried ;)")
			break
		}
		// ### 2. increase the current direction to try the next possibility
		path.IncCurrentDir()
		// ### 3. check if rotation is finished. Then backtrack
		if path.CurrentCounter() > 3 {
			var dir = path.Current().PopIgnored()
			if dir == -1 {
				log.D(e.Id, "Rotation finished. Deadlock. Backtrack.")
				e.UndoStep()
				path.Pop()
				continue
			} else {
				path.SetCurrentDir(dir)
				ignoredDir = true
			}
		}
		// ### 4a. check if there is a box in direction dir and if this box is on a point
		cf := e.FigPos()                        // current figureposition
		nf := cf.Add(path.CurrentDir().Point()) // potential new figureposition
		if e.Surface[nf.Y][nf.X].Point && e.Surface[nf.Y][nf.X].Box != 0 && !ignoredDir {
			log.D(e.Id, "Do not moving a box from a point")
			path.Current().PushIgnored(path.CurrentDir())
			continue
		}
		// ### 4b. Try moving
		log.D(e.Id, "Try moving in dir=%d", path.CurrentDir())
		moved, boxMoved := e.Move(path.CurrentDir())
		if !moved {
			log.D(e.Id, "Could not move.")
			continue
		}
		// ### 5. If moved, first check if not in a loop
		newHist := e.GetBoxesAndX()
		if everBeenHere(&history, newHist) {
			log.D(e.Id, "I'v been here already. Backtrack: %d", newHist)
			e.UndoStep()
			continue
		}
		// ### 6. If not in a loop, append history and go on
		addHistory(&history, newHist)
		if straightAhead {
			path.Push(path.CurrentDir() - 1)
		} else {
			path.Push(-1)
		}
		log.D(e.Id, "Moved. Path added.")
		// ### 7. Do some statistics
		incSteps()
		if printSurface {
			e.Print()
		}
		if steps%outputFreq == 0 {
			min, sec, µsec := getTimePassed(starttime)
			log.I(gorNo, "Steps: %9d; %4dm %2ds %6dµs", steps, min, sec, µsec)
		}
		// ### 8. Do we already won? :)
		if boxMoved != 0 && e.Won() {
			incSolutions()
			min, sec, µsec := getTimePassed(starttime)
			stepsCpy := steps
			log.Lock <- 1
			log.A("%d. solution found after %d steps, %4dm %2ds %6dµs.\nPath: %d%d\n", solutions, stepsCpy, min, sec, µsec, basePath.Directions(), path.Directions())
			<-log.Lock
			e.Print()
			solSteps = append(solSteps, stepsCpy)
			if single {
				running = false
				break
			}
			e.UndoStep()
			path.Pop()
		}
		// ### 9. Decide if we just go on or if we start a new thread
		if len(cDone) < threads {
			wg.Add(1)
			cDone <- 1
			ne := e.Clone()
			log.I(gorNo, "Creating new worker")
			go runWorker(ne, path.Clone(), threads, single, outputFreq, printSurface, straightAhead)
			// go back, as we deligated current dir go worker
			//			time.Sleep(3 * time.Second)
			e.UndoStep()
			path.Pop()
		}

	}
	<-cDone
	log.I(gorNo, "runWorker %d finished", gorNo)
}