This repository was archived by the owner on May 20, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
first version, written at an airport
- Loading branch information
1 parent
fcd5f14
commit 7b2d2ae
Showing
11 changed files
with
513 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mikehelmick |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
name: Go | ||
|
||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
branches: [ main ] | ||
|
||
jobs: | ||
|
||
build: | ||
name: Build | ||
runs-on: ubuntu-latest | ||
steps: | ||
|
||
- name: Set up Go 1.x | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: ^1.20 | ||
id: go | ||
|
||
- name: Check out code into the Go module directory | ||
uses: actions/checkout@v2 | ||
|
||
- name: Get dependencies | ||
run: | | ||
go get -v -t -d ./... | ||
if [ -f Gopkg.toml ]; then | ||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh | ||
dep ensure | ||
fi | ||
- name: Build | ||
run: go build -v ./... | ||
|
||
- name: Test | ||
run: go test -v ./... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,33 @@ | ||
# digits-helper | ||
# digits-helper | ||
|
||
A solve for the NYTimes Digits game! | ||
https://www.nytimes.com/games/digits | ||
|
||
To run from source | ||
|
||
1. Clone the repo | ||
2. Run with go run | ||
|
||
This does not try to find the 'best' solution or list all solutions. | ||
It just lists the first one that we find. | ||
|
||
## Examples | ||
|
||
``` | ||
❯ go run . 59 2 3 5 11 15 25 | ||
*** SOLUTION *** | ||
25 + 15 | ||
40 + 11 | ||
51 + 5 | ||
56 + 3 | ||
``` | ||
|
||
``` | ||
❯ go run . 133 4 5 8 11 15 20 | ||
*** SOLUTION *** | ||
20 + 15 | ||
35 - 11 | ||
24 + 8 | ||
32 * 4 | ||
128 + 5 | ||
``` |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
module github.com/mikehelmick/digits-helper | ||
|
||
go 1.20 | ||
|
||
require github.com/google/go-cmp v0.5.9 | ||
|
||
require golang.org/x/exp v0.0.0-20220516143420-24438e51023a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= | ||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
golang.org/x/exp v0.0.0-20220516143420-24438e51023a h1:tiLLxEjKNE6Hrah/Dp/cyHvsyjDLcMFSocOHO5XDmOM= | ||
golang.org/x/exp v0.0.0-20220516143420-24438e51023a/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/mikehelmick/digits-helper/pkg/digits" | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
args := flag.Args() | ||
|
||
if len(args) != 7 { | ||
log.Fatalf("7 arguments are required `target` and the 6 digits") | ||
} | ||
|
||
intArgs := make([]int, len(args)) | ||
for i, v := range args { | ||
converted, err := strconv.ParseInt(v, 10, 32) | ||
if err != nil { | ||
log.Fatalf("Unable to convert argument: %v reason: %v", v, err) | ||
} | ||
intArgs[i] = int(converted) | ||
} | ||
|
||
s, err := digits.New(intArgs[0], intArgs[1:]) | ||
if err != nil { | ||
log.Fatalf("unable to initialize solver: %v", err) | ||
} | ||
|
||
solution, err := s.Solve() | ||
if err != nil { | ||
log.Fatalf("unable to solve: %v", err) | ||
} | ||
fmt.Printf("*** SOLUTION ***\n%v\n", strings.Join(solution, "\n")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package digits | ||
|
||
import "fmt" | ||
|
||
type Operation interface { | ||
Can(a, b int) bool | ||
Op(a, b int) int | ||
String(a, b int) string | ||
} | ||
|
||
var ( | ||
AllOperations = []Operation{ | ||
&Addition{}, | ||
&Subtraction{}, | ||
&Multiplication{}, | ||
&Division{}, | ||
} | ||
|
||
OpAddition = &Addition{} | ||
OpSubtraction = &Subtraction{} | ||
OpMultiplication = &Multiplication{} | ||
OpDivision = &Division{} | ||
) | ||
|
||
type Addition struct{} | ||
|
||
func (op *Addition) Can(a, b int) bool { return true } | ||
|
||
func (op *Addition) Op(a, b int) int { | ||
return a + b | ||
} | ||
|
||
func (op *Addition) String(a, b int) string { | ||
return fmt.Sprintf("%v + %v", a, b) | ||
} | ||
|
||
type Subtraction struct{} | ||
|
||
func (op *Subtraction) Can(a, b int) bool { return true } | ||
|
||
func (op *Subtraction) Op(a, b int) int { | ||
return a - b | ||
} | ||
|
||
func (op *Subtraction) String(a, b int) string { | ||
return fmt.Sprintf("%v - %v", a, b) | ||
} | ||
|
||
type Multiplication struct{} | ||
|
||
func (op *Multiplication) Can(a, b int) bool { return true } | ||
|
||
func (op *Multiplication) Op(a, b int) int { | ||
return a * b | ||
} | ||
|
||
func (op *Multiplication) String(a, b int) string { | ||
return fmt.Sprintf("%v * %v", a, b) | ||
} | ||
|
||
type Division struct{} | ||
|
||
func (op *Division) Can(a, b int) bool { | ||
if b == 0 { | ||
return false | ||
} | ||
return a%b == 0 | ||
} | ||
|
||
func (op *Division) Op(a, b int) int { | ||
return a / b | ||
} | ||
|
||
func (op *Division) String(a, b int) string { | ||
return fmt.Sprintf("%v / %v", a, b) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package digits | ||
|
||
import "testing" | ||
|
||
func TestAddition(t *testing.T) { | ||
op := &Addition{} | ||
if !op.Can(1, 2) { | ||
t.Fatalf("addition always can...") | ||
} | ||
|
||
res := op.Op(1, 2) | ||
if res != 3 { | ||
t.Fatalf("addition got wrong result 1+2 = %v", res) | ||
} | ||
} | ||
|
||
func TestSubtraction(t *testing.T) { | ||
op := &Subtraction{} | ||
if !op.Can(10, 6) { | ||
t.Fatalf("subtraction always can...") | ||
} | ||
|
||
res := op.Op(10, 6) | ||
if res != 4 { | ||
t.Fatalf("subtraction got wrong result 10-6 = %v", res) | ||
} | ||
} | ||
|
||
func TestMultiplication(t *testing.T) { | ||
op := &Multiplication{} | ||
if !op.Can(10, 6) { | ||
t.Fatalf("multiplication always can...") | ||
} | ||
|
||
res := op.Op(10, 6) | ||
if res != 60 { | ||
t.Fatalf("subtraction got wrong result 10*6 = %v", res) | ||
} | ||
} | ||
|
||
func TestDivision(t *testing.T) { | ||
op := &Division{} | ||
if op.Can(10, 3) { | ||
t.Fatalf("division shouldn't be able to 10/3") | ||
} | ||
|
||
if !op.Can(9, 3) { | ||
t.Fatalf("division should be able to 9/3") | ||
} | ||
|
||
res := op.Op(9, 3) | ||
if res != 3 { | ||
t.Fatalf("division got wrong result 9/3 = %v", res) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package digits | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"golang.org/x/exp/slices" | ||
) | ||
|
||
type Solver struct { | ||
target int | ||
digits []int | ||
operations []string | ||
solved bool | ||
} | ||
|
||
var ( | ||
ErrorInvalidOp = errors.New("invalid operation") | ||
) | ||
|
||
func New(target int, digits []int) (*Solver, error) { | ||
if target <= 0 || target > 2000 { | ||
return nil, fmt.Errorf("target must be >0 and <= 2000") | ||
} | ||
if l := len(digits); l != 6 { | ||
return nil, fmt.Errorf("6 digits are required to start a new puzzle, got: %v", l) | ||
} | ||
for _, d := range digits { | ||
if d <= 0 || d >= 200 { | ||
return nil, fmt.Errorf("starting digits must be > 0 and <= 200, got: %v", d) | ||
} | ||
} | ||
|
||
digs := make([]int, len(digits)) | ||
copy(digs, digits) | ||
|
||
slices.SortFunc(digs, func(i, j int) bool { | ||
return i > j | ||
}) | ||
|
||
return &Solver{ | ||
target: target, | ||
digits: digs, | ||
operations: make([]string, 0), | ||
}, nil | ||
} | ||
|
||
func (s *Solver) next(a, b int, op Operation) (*Solver, error) { | ||
if len(s.digits) < 2 { | ||
return nil, fmt.Errorf("not enough digits to perform operation") | ||
} | ||
if !op.Can(a, b) { | ||
return nil, ErrorInvalidOp | ||
} | ||
|
||
foundA, foundB := false, false | ||
newD := make([]int, 0, len(s.digits)-2) | ||
for _, d := range s.digits { | ||
if d == a && !foundA { | ||
foundA = true | ||
continue | ||
} | ||
if d == b && !foundB { | ||
foundB = true | ||
continue | ||
} | ||
newD = append(newD, d) | ||
} | ||
ops := make([]string, len(s.operations)) | ||
copy(ops, s.operations) | ||
|
||
// Do the operation | ||
res := op.Op(a, b) | ||
newD = append(newD, res) | ||
slices.SortFunc(newD, func(i, j int) bool { | ||
return i > j | ||
}) | ||
|
||
return &Solver{ | ||
target: s.target, | ||
digits: newD, | ||
operations: append(ops, op.String(a, b)), | ||
solved: s.target == res, | ||
}, nil | ||
} | ||
|
||
func (s *Solver) Solve() ([]string, error) { | ||
|
||
for i := 0; i < len(s.digits)-1; i++ { | ||
for j := i + 1; j < len(s.digits); j++ { | ||
for _, op := range AllOperations { | ||
a := s.digits[i] | ||
b := s.digits[j] | ||
|
||
n, err := s.next(a, b, op) | ||
if err != nil { | ||
continue | ||
} | ||
|
||
if n.solved { | ||
return n.operations, nil | ||
} | ||
// else try to solve from there | ||
res, err := n.Solve() | ||
if res == nil { | ||
continue | ||
} | ||
return res, nil | ||
} | ||
} | ||
} | ||
|
||
return nil, fmt.Errorf("no solutions found") | ||
} |
Oops, something went wrong.