wox
8/9/2012 - 12:32 PM

Solitare

Solitare

import math.{max,min}
import util.Random.shuffle

case class Card(suit:Int, rank:Int) {
	def switchableWith(c:Card) = suit==c.suit || rank==c.rank
}

case class Deck(cards: List[Card]) {
	def switchable(i: Int, dx: Int) = (dx <= i && (cards(i) switchableWith cards(i-dx)) )
	
	def switch(i: Int, dx: Int) = {
		val(head, rest) = cards splitAt i-dx
		val(mid, tail) = rest splitAt dx
		Deck( head ::: tail.take(1) ::: mid.drop(1) ::: tail.drop(1) )
	}
}

object Deck {
	val cards = for (suit <- 1 to 4; rank <- 1 to 13) yield Card(suit,rank)
	
	def apply(seed: Int): Deck = {
		util.Random.setSeed(seed)
		Deck( shuffle(cards.toList) )
	} 
}

def play(deck: Deck, i: Int): Boolean = {
	if (deck.cards.length == 1) {
		true	
	} else if (i >= deck.cards.length ) {
		false
	} else {
		val s1 = deck.switchable(i,1)
		val s3 = deck.switchable(i,3)

		if (!s1 && !s3)
			play( deck, i+1 )
		else
			( if (s1) play( deck.switch(i, 1), max(i-1,1) ) else false ) ||
			( if (s3) play( deck.switch(i, 3), max(i-3,1) ) else false )
	}
}

def run(numberOfRuns: Int) = (1 to numberOfRuns).foldLeft(0) { 
	(acc,i) => { if( play(Deck(i), 1) ) acc+1 else acc } 
} 

println( run(100) )