From 479a6c18f01aae861ccaf0831f5a31d2b201af88 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 17:27:30 -0600 Subject: [PATCH 01/10] day 6 - add nolint directives where xor of addresses are inherently unsafe by design --- day6/problem.go | 6 +++--- day6/problem_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/day6/problem.go b/day6/problem.go index 67f26c3..f819791 100644 --- a/day6/problem.go +++ b/day6/problem.go @@ -18,11 +18,11 @@ func New(val interface{}) *XorList { // Add adds a new value func (xl *XorList) Add(val interface{}) { prev := uintptr(0) - this := unsafe.Pointer(xl) + this := unsafe.Pointer(xl) // nolint: gosec for prev^xl.both != 0 { - prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) + prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) // nolint: vet, gosec xl = (*XorList)(this) } nxl := &XorList{val: val, both: uintptr(this)} - xl.both = prev ^ uintptr(unsafe.Pointer(nxl)) + xl.both = prev ^ uintptr(unsafe.Pointer(nxl)) // nolint: gosec } diff --git a/day6/problem_test.go b/day6/problem_test.go index 2c86768..b16a422 100644 --- a/day6/problem_test.go +++ b/day6/problem_test.go @@ -57,7 +57,7 @@ func backwardToSlice(xl *XorList) []interface{} { prev := uintptr(0) this := unsafe.Pointer(xl) for prev^xl.both != 0 { - prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) + prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) // nolint: vet xl = (*XorList)(this) } // now collect items from tail to the head @@ -66,7 +66,7 @@ func backwardToSlice(xl *XorList) []interface{} { this = unsafe.Pointer(xl) result = append(result, xl.val) for prev^xl.both != 0 { - prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) + prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) // nolint: vet xl = (*XorList)(this) result = append(result, xl.val) } @@ -81,7 +81,7 @@ func forwardToSlice(xl *XorList) []interface{} { this := unsafe.Pointer(xl) result = append(result, xl.val) for prev^xl.both != 0 { - prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) + prev, this = uintptr(this), unsafe.Pointer(prev^xl.both) // nolint: vet xl = (*XorList)(this) result = append(result, xl.val) } From 83ee3f0c739385d783242a0e4afb810001870d69 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 17:30:39 -0600 Subject: [PATCH 02/10] day 10 - nolint where time format is controlled internally. --- day10/problem.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/day10/problem.go b/day10/problem.go index f9381da..67698d1 100644 --- a/day10/problem.go +++ b/day10/problem.go @@ -28,7 +28,7 @@ func NewScheduler() *Scheduler { for j := range s.queue { s.wg.Add(1) go func(j job) { - ms, _ := time.ParseDuration(fmt.Sprintf("%dms", j.n)) + ms, _ := time.ParseDuration(fmt.Sprintf("%dms", j.n)) // nolint: gosec time.Sleep(ms) log.Printf("starting job at %dms", convertNanoToMillis(time.Since(s.startTime).Nanoseconds())) j.f() From a093cace6d360dbbdbfd6a9459f26f83da0b0b29 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 17:32:57 -0600 Subject: [PATCH 03/10] day 28 - nolint WriteString because it always returns nil for error --- day28/problem.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/day28/problem.go b/day28/problem.go index ca01e3d..51cb333 100644 --- a/day28/problem.go +++ b/day28/problem.go @@ -37,7 +37,7 @@ func buildLine(line []string, k, lineLength int) string { minimumSpaces := (k - lineLength) / len(line) extraSpaces := k - lineLength - ((len(line) - 1) * minimumSpaces) for i, word := range line { - sb.WriteString(word) + sb.WriteString(word) // nolint: gosec if i == len(line)-1 { break } @@ -45,7 +45,7 @@ func buildLine(line []string, k, lineLength int) string { if i < extraSpaces { spaces++ } - sb.WriteString(strings.Repeat(" ", spaces)) + sb.WriteString(strings.Repeat(" ", spaces)) // nolint: gosec } return sb.String() } From ac80fc534cf1e31ce0acd88726c2cad9256f528e Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 17:34:24 -0600 Subject: [PATCH 04/10] day 29 - nolint WriteString because it always returns nil for error --- day29/problem.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/day29/problem.go b/day29/problem.go index c520166..517f82b 100644 --- a/day29/problem.go +++ b/day29/problem.go @@ -18,14 +18,14 @@ func RunLengthEncoding(str string) string { } else if r == last { count++ } else { - sb.WriteString(strconv.Itoa(count)) - sb.WriteString(string(last)) + sb.WriteString(strconv.Itoa(count)) // nolint: gosec + sb.WriteString(string(last)) // nolint: gosec count = 1 last = r } } - sb.WriteString(strconv.Itoa(count)) - sb.WriteString(string(last)) + sb.WriteString(strconv.Itoa(count)) // nolint: gosec + sb.WriteString(string(last)) // nolint: gosec return sb.String() } @@ -35,13 +35,13 @@ func RunLengthDecoding(str string) string { var count int for _, r := range str { if r >= 'A' && r <= 'Z' { - sb.WriteString(strings.Repeat(string(r), count)) + sb.WriteString(strings.Repeat(string(r), count)) // nolint: gosec count = 0 } else { if count != 0 { count *= 10 } - digit, _ := strconv.Atoi(string(r)) + digit, _ := strconv.Atoi(string(r)) // nolint: gosec count += digit } } From b63498d8ea1805bc0d23f510ad7f73049d7bce58 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 17:35:45 -0600 Subject: [PATCH 05/10] day 39 - nolint WriteString because it always returns nil for error --- day39/problem.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/day39/problem.go b/day39/problem.go index 11e64f3..84e5a4c 100644 --- a/day39/problem.go +++ b/day39/problem.go @@ -43,12 +43,12 @@ func (gol *GameOfLife) String() string { for y := gol.maxY - 1; y > gol.minY; y-- { for x := gol.minX + 1; x < gol.maxX; x++ { if _, alive := gol.living[Coord{x, y}]; alive { - sb.WriteRune('*') + sb.WriteRune('*') // nolint: gosec } else { - sb.WriteRune('.') + sb.WriteRune('.') // nolint: gosec } } - sb.WriteRune('\n') + sb.WriteRune('\n') // nolint: gosec } return sb.String() } From 97d75bbde9b35fa054d4e957d13103a7c9757583 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 19:30:01 -0600 Subject: [PATCH 06/10] day 25 - gocyclo. considerably slower due to function. 12892 ns/op->30000 --- day25/problem.go | 49 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/day25/problem.go b/day25/problem.go index 4dea70d..1672838 100644 --- a/day25/problem.go +++ b/day25/problem.go @@ -3,28 +3,55 @@ package day25 // Match returns if there is a regex match on the given input. func Match(input, pattern string) bool { var ii, pi, missed int - for ii < len(input) && pi < len(pattern) && missed < 2 { - if pattern[pi] == '*' { - prev := pattern[pi-1] - var next byte - if pi+1 < len(pattern) { - next = pattern[pi+1] + inputR := []rune(input) + patternR := []rune(pattern) + for isPossible(ii, len(inputR), pi, len(patternR), missed) { + if patternR[pi] == '*' { + prev := patternR[pi-1] + var next rune + if pi+1 < len(patternR) { + next = patternR[pi+1] } - for ii < len(input) && input[ii] != next { - if prev != '.' && input[ii] != prev { + for shouldKeepLooking(ii, len(inputR), inputR, next) { + if prev != '.' && inputR[ii] != prev { return false } ii++ } - if ii == len(input) && pi < len(pattern)-1 { + if remainingPattern(ii, len(inputR), pi, len(patternR)) { return false } ii-- - } else if pattern[pi] != '.' && input[ii] != pattern[pi] { + } else if missedMatch(patternR[pi], inputR[ii]) { missed++ } ii++ pi++ } - return ii == len(input) && pi == len(pattern) + return finished(ii, len(input), pi, len(pattern)) +} + +// finished is true if we've completed processing the input and pattern strings. +func finished(inputIndex, inputSize, patternIndex, patternSize int) bool { + return inputIndex == inputSize && patternIndex == patternSize +} + +// isPossible returns true if its possible the pattern could still match. +func isPossible(inputIndex, inputSize, patternIndex, patternSize, numMissed int) bool { + return inputIndex < inputSize && patternIndex < patternSize && numMissed < 2 +} + +// missedMatch returns true if a match was missed. +func missedMatch(patternRune, inputRune rune) bool { + return patternRune != '.' && inputRune != patternRune +} + +// remainingPattern returns true if we finished processing the input, but still have pattern remaining. +func remainingPattern(inputIndex, inputSize, patternIndex, patternSize int) bool { + return inputIndex == inputSize && patternIndex < patternSize-1 +} + +// shouldKeepLooking returns true if the wildcard should continue looking at the input. +func shouldKeepLooking(inputIndex, inputSize int, inputR []rune, next rune) bool { + return inputIndex < inputSize && inputR[inputIndex] != next } From 11740549cc4357a0502196a297765bf94dce0589 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 19:37:57 -0600 Subject: [PATCH 07/10] day 27 - gocyclo drop by performance hit 7918 ns/op->20556 ns/op --- day27/problem.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/day27/problem.go b/day27/problem.go index 47fbc78..074bdda 100644 --- a/day27/problem.go +++ b/day27/problem.go @@ -5,9 +5,9 @@ package day27 func WellBalanced(brackets string) bool { openBrackets := make([]rune, 0, (len(brackets)/2)+1) for _, r := range brackets { - if r == '(' || r == '[' || r == '{' { + if matchAnyRune(r, '(', '[', '{') { openBrackets = append(openBrackets, r) - } else if r == ')' || r == ']' || r == '}' { + } else if matchAnyRune(r, ')', ']', '}') { if len(openBrackets) == 0 { return false } @@ -24,6 +24,15 @@ func WellBalanced(brackets string) bool { return len(openBrackets) == 0 } +// matchAnyRune will return true if the source matches any of the supplied targets. +func matchAnyRune(source rune, targets ...rune) bool { + var result bool + for _, r := range targets { + result = result || (source == r) + } + return result +} + // IsMatch returns true if the left and right runes form a matching pair. func IsMatch(left, right rune) bool { return (right == ')' && left == '(') || From 79349c399b0eda54107e8c40797d645a8b5c53ec Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 19:40:24 -0600 Subject: [PATCH 08/10] day 43 - gocyclo remove redundant check of error --- day43/problem_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/day43/problem_test.go b/day43/problem_test.go index bb9f895..c275624 100644 --- a/day43/problem_test.go +++ b/day43/problem_test.go @@ -15,17 +15,17 @@ func TestMaxIntStack(t *testing.T) { stack := NewMaxIntStack() for i, push := range tc.input { stack.Push(push) - if max, err := stack.Max(); err != nil || max != tc.max[i] { + if max, err := stack.Max(); max != tc.max[i] { t.Errorf("TC%d push expected,got max (%d,%d) error should be nil (%v)", tcid, tc.max[i], max, err) } } for i := range tc.input { - if max, err := stack.Max(); err != nil || max != tc.max[len(tc.max)-1-i] { + if max, err := stack.Max(); max != tc.max[len(tc.max)-1-i] { t.Errorf("TC%d pre-pop expected,got max (%d,%d) error should be nil (%v)", tcid, tc.max[len(tc.max)-1-i], max, err) } - if val, err := stack.Pop(); err != nil || val != tc.input[len(tc.input)-1-i] { + if val, err := stack.Pop(); val != tc.input[len(tc.input)-1-i] { t.Errorf("TC%d pop expected,got val (%d,%d) error should be nil (%v)", tcid, tc.input[len(tc.input)-1-i], val, err) } From 7395c88d631e09061afc17146cb1ec8f47ab6012 Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 19:43:00 -0600 Subject: [PATCH 09/10] day 32 - gocyclo refactor --- day32/problem.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/day32/problem.go b/day32/problem.go index 97b32f8..9b36100 100644 --- a/day32/problem.go +++ b/day32/problem.go @@ -7,13 +7,7 @@ import "math" // Uses Bellman-Ford Shortest Path which runs in O(N^3) time and O(N^2) space // due to the transformed rates table. func Arbitrage(rates [][]float64) bool { - graph := make([][]float64, len(rates)) - for i := range graph { - graph[i] = make([]float64, len(rates[i])) - for j := range graph[i] { - graph[i][j] = -math.Log(rates[i][j]) - } - } + graph := createGraph(rates) source := 0 minDist := make([]float64, len(rates)) for i := range minDist { @@ -39,3 +33,14 @@ func Arbitrage(rates [][]float64) bool { } return false } + +func createGraph(rates [][]float64) [][]float64 { + graph := make([][]float64, len(rates)) + for i := range graph { + graph[i] = make([]float64, len(rates[i])) + for j := range graph[i] { + graph[i][j] = -math.Log(rates[i][j]) + } + } + return graph +} From 9404928bf830226d42b493197a96832919a30a7a Mon Sep 17 00:00:00 2001 From: Vasko Zdravevski Date: Wed, 3 Oct 2018 19:51:40 -0600 Subject: [PATCH 10/10] sudoku - gocyclo refactor --- sudoku/problem.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sudoku/problem.go b/sudoku/problem.go index c8b13c2..e8467f9 100644 --- a/sudoku/problem.go +++ b/sudoku/problem.go @@ -20,7 +20,7 @@ func Solver(board Board, n int) (Board, bool) { } } for j := 0; j < n*n; j++ { - if board[n*n*j+col] == choice || board[row*n*n+j] == choice { + if matchAnyInt(choice, board[n*n*j+col], board[row*n*n+j]) { isValid = false break } @@ -38,6 +38,14 @@ func Solver(board Board, n int) (Board, bool) { return board, false } +func matchAnyInt(source int, targets ...int) bool { + var result bool + for _, target := range targets { + result = result || (source == target) + } + return result +} + func findEmpty(board Board, n int) (int, int, bool) { for i, box := range board { if box == 0 {