From df5343c59bf70a4df455f55141f7ece797dc5b9f Mon Sep 17 00:00:00 2001 From: CJ Cullen Date: Wed, 28 Dec 2016 14:34:25 -0800 Subject: [PATCH] Initial commit. --- main.go | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 main.go diff --git a/main.go b/main.go new file mode 100644 index 0000000..8218af8 --- /dev/null +++ b/main.go @@ -0,0 +1,211 @@ +package main + +import ( + "fmt" + "math" + "sort" +) + +const numCards = 4 +const maxCard = 10.0 +const targetNum = 24.0 + +var operators = []operator{AddOp, SubOp, MulOp, DivOp} +var treeCache = make(map[string][]node) +var neededTrees = make(map[string]node) + +func main() { + possible := 0 + + all := allDeals([]float64{}) + + for i, deal := range all { + tree := getNeededTree(deal, targetNum) + if tree != nil { + possible++ + fmt.Printf("%d. %v: %s\n", i, deal, tree.getExp()) + } else { + fmt.Printf("%d. %v: not possible\n", i, deal) + } + } + + fmt.Printf("%d / %d possible\n", possible, len(all)) +} + +func allDeals(partialDeal []float64) [][]float64 { + if len(partialDeal) == numCards { + return [][]float64{partialDeal} + } + lastCard := 1.0 + if len(partialDeal) > 0 { + lastCard = partialDeal[len(partialDeal)-1] + } + var all [][]float64 + for i := lastCard; i <= maxCard; i++ { + newPartial := append([]float64{}, partialDeal...) + newPartial = append(newPartial, i) + all = append(all, allDeals(newPartial)...) + } + return all +} + +func getPossibleTrees(deal []float64) []node { + ds := dealString(deal) + if nodes, ok := treeCache[ds]; ok { + return nodes + } + if len(deal) == 1 { + return []node{&valNode{deal[0]}} + } + var trees []node + for i := 1; i < 1<>uint64(bit))%2 == 0 { + leftCards = append(leftCards, deal[bit]) + } else { + rightCards = append(rightCards, deal[bit]) + } + } + return leftCards, rightCards +} + +type node interface { + getVal() float64 + getExp() string +} + +// valNode is a value node in the expression tree. +type valNode struct { + val float64 +} + +func (v *valNode) getVal() float64 { return v.val } + +func (v *valNode) getExp() string { return fmt.Sprintf("%v", v.val) } + +// opNode is an binary operator node in the expression tree. +type opNode struct { + op operator + left node + right node +} + +func (o *opNode) getVal() float64 { return o.op.compute(o.left.getVal(), o.right.getVal()) } + +func (o *opNode) getExp() string { + return fmt.Sprintf("(%s %s %s)", o.left.getExp(), o.op.opString(), o.right.getExp()) +} + +type operator interface { + compute(left, right float64) float64 + computeNecessary(left, right float64) float64 + opString() string +} + +type addOp struct{} + +func (*addOp) compute(left, right float64) float64 { return left + right } + +func (*addOp) computeNecessary(left, want float64) float64 { return want - left } + +func (*addOp) opString() string { return "+" } + +var AddOp = &addOp{} + +type subOp struct{} + +func (*subOp) compute(left, right float64) float64 { return left - right } + +func (*subOp) computeNecessary(left, want float64) float64 { return left - want } + +func (*subOp) opString() string { return "-" } + +var SubOp = &subOp{} + +type mulOp struct{} + +func (*mulOp) compute(left, right float64) float64 { return left * right } + +func (*mulOp) computeNecessary(left, want float64) float64 { return want / left } + +func (*mulOp) opString() string { return "*" } + +var MulOp = &mulOp{} + +type divOp struct{} + +func (*divOp) compute(left, right float64) float64 { return left / right } + +func (*divOp) computeNecessary(left, want float64) float64 { return left / want } + +func (*divOp) opString() string { return "/" } + +var DivOp = &divOp{}