update
parent
8128450d54
commit
44b67f0de4
@ -0,0 +1,23 @@
|
||||
package q04
|
||||
|
||||
func waterCorners(grid [][]rune, x, y int) int {
|
||||
isWater := func(x, y int) int {
|
||||
if x < 0 || y < 0 || x >= len(grid) || y >= len(grid[x]) || grid[x][y] == ' ' {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return isWater(x-1, y) + isWater(x+1, y) + isWater(x, y-1) + isWater(x, y+1)
|
||||
}
|
||||
|
||||
func solveP1(grid [][]rune) int {
|
||||
var ps int
|
||||
for x := range grid {
|
||||
for y := range grid[x] {
|
||||
if waterCorners(grid, x, y) == 3 {
|
||||
ps++
|
||||
}
|
||||
}
|
||||
}
|
||||
return ps
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package q04
|
||||
|
||||
func check(x, y, n, m int) bool {
|
||||
return x >= 0 && y >= 0 && x < n && y < m
|
||||
}
|
||||
|
||||
var dirs = [][]int{{-1, 0}, {0, -1}, {1, 0}, {0, 1}}
|
||||
|
||||
func dfs(grid [][]rune, vis [][]bool, x, y, n, m int) {
|
||||
if !check(x, y, n, m) || grid[x][y] == ' ' || vis[x][y] {
|
||||
return
|
||||
}
|
||||
vis[x][y] = true
|
||||
for _, d := range dirs {
|
||||
x1, y1 := x+d[0], y+d[1]
|
||||
dfs(grid, vis, x1, y1, n, m)
|
||||
}
|
||||
}
|
||||
|
||||
func solveP2(grid [][]rune) int {
|
||||
var res int
|
||||
n := len(grid)
|
||||
m := len(grid[0])
|
||||
vis := make([][]bool, n)
|
||||
for i := range vis {
|
||||
vis[i] = make([]bool, m)
|
||||
}
|
||||
for i := range grid {
|
||||
for j := range grid[i] {
|
||||
if !vis[i][j] && grid[i][j] == 'X' {
|
||||
res++
|
||||
dfs(grid, vis, i, j, n, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package q04
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/hhhapz/codequest/models"
|
||||
"github.com/hhhapz/codequest/question"
|
||||
)
|
||||
|
||||
type boolgen struct {
|
||||
src *rand.Rand
|
||||
cache int64
|
||||
remaining int
|
||||
}
|
||||
|
||||
func (b *boolgen) Bool() bool {
|
||||
if b.remaining == 0 {
|
||||
b.cache, b.remaining = b.src.Int63(), 63
|
||||
}
|
||||
|
||||
result := b.cache&0x01 == 1
|
||||
b.cache >>= 1
|
||||
b.remaining--
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func init() {
|
||||
t := template.New("island")
|
||||
var err error
|
||||
t, err = t.Parse(q03Text)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
question.Register(
|
||||
&question.Question{
|
||||
ID: "island",
|
||||
Name: "Island Analysis",
|
||||
Text: t,
|
||||
Level: question.Level2,
|
||||
Generate: func(u *models.User) string {
|
||||
inp := generate(u)
|
||||
res := make([]string, 0, rows)
|
||||
|
||||
for _, row := range inp {
|
||||
res = append(res, string(row))
|
||||
}
|
||||
return strings.Join(res, "\n")
|
||||
},
|
||||
Validate: func(u *models.User, part question.Part, solution string) bool {
|
||||
return Validate(u, part, solution)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
rows = 90
|
||||
cols = 50
|
||||
)
|
||||
|
||||
func generate(u *models.User) [][]rune {
|
||||
res := make([][]rune, rows)
|
||||
|
||||
b := boolgen{
|
||||
src: question.UserRandom(u),
|
||||
}
|
||||
|
||||
for i := 0; i < rows; i++ {
|
||||
res[i] = make([]rune, cols)
|
||||
for j := 0; j < cols; j++ {
|
||||
m := 'X'
|
||||
if b.Bool() {
|
||||
m = ' '
|
||||
}
|
||||
res[i][j] = m
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func Validate(u *models.User, p question.Part, sol string) bool {
|
||||
inp := generate(u)
|
||||
|
||||
var n int
|
||||
switch p {
|
||||
case question.Part1:
|
||||
n = solveP1(inp)
|
||||
case question.Part2:
|
||||
n = solveP2(inp)
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
fmt.Println("submitted", u.Name, p, sol)
|
||||
fmt.Println("actual", u.Name, p, n)
|
||||
|
||||
return strconv.Itoa(n) == sol
|
||||
}
|
||||
|
||||
//go:embed q04.md
|
||||
var q03Text string
|
@ -0,0 +1,107 @@
|
||||
You decide to visit the archipelagos of Indonesia. You find a map of the area near South Sulawesi,
|
||||
and can see where there is land (marked with an `X`), and where the ocean is (empty space).
|
||||
|
||||
You and your friends decide you want to stay at the islands for the weekend.
|
||||
|
||||
However, there are so many islands to pick from, and you have no way to decide which one to pick to
|
||||
stay at. To make a decision, you come up with a plan.
|
||||
|
||||
Firstly, you have decided that the location needs to be a peninsula. That means, water on 3 sides,
|
||||
and land on one side.
|
||||
|
||||
### Note:
|
||||
|
||||
> When counting peninsulas, do not consider diagonal tiles. Only consider those directly to the left,
|
||||
> right, above and below the tile.
|
||||
|
||||
> The (invisible) edges of the input all count after the water tiles.
|
||||
|
||||
### Example
|
||||
|
||||
Given the following input:
|
||||
|
||||
```
|
||||
ABCDE
|
||||
1. X XX
|
||||
2. X X
|
||||
3. X
|
||||
4. XX X
|
||||
```
|
||||
|
||||
Contains 4 peninsulas:
|
||||
|
||||
* 1D
|
||||
* 3D
|
||||
* 4A
|
||||
* 4B
|
||||
|
||||
---
|
||||
|
||||
Given the following input:
|
||||
|
||||
```
|
||||
ABCDEFGH
|
||||
1 XXX XX
|
||||
2 X XX X
|
||||
3 XXXXX X
|
||||
4 X X
|
||||
5 X XXXX
|
||||
6 XX XXXX
|
||||
|
||||
```
|
||||
|
||||
Contains 9 peninsulas:
|
||||
|
||||
* 1C
|
||||
* 1H
|
||||
* 2B
|
||||
* 3A
|
||||
* 4D
|
||||
* 5A
|
||||
* 5H
|
||||
* 6B
|
||||
* 6D
|
||||
|
||||
To get the answer for part one, **what is the total number of peninsulas you can count on your
|
||||
map?**
|
||||
|
||||
{{ if .Part1.Completed -}}
|
||||
|
||||
**Congratulations! You got Part 1 correct. Your answer was `{{ .Part1.Solution }}`.**
|
||||
|
||||
## Part 2
|
||||
|
||||
With the number of peninsulas that are in the lake, you are having trouble determining which one to
|
||||
pick. In order to do so, you have devised a plan to try to see which island has the most number of
|
||||
peninsulas.
|
||||
|
||||
In order to do this, though, we first need to count how many islands we have.
|
||||
|
||||
An island is a contiguous set of grids, that are connected by water in at least one of the four
|
||||
directions, similar to a peninsula.
|
||||
|
||||
### Example
|
||||
|
||||
Given the following input:
|
||||
|
||||
```
|
||||
ABCDEFGH
|
||||
1 XXX XX
|
||||
2 X XX X
|
||||
3 XXXXX X
|
||||
4 X X
|
||||
5 X XXXX
|
||||
6 XX XXXX
|
||||
|
||||
```
|
||||
|
||||
There are 3 distinct islands.
|
||||
|
||||
**What is the total number of islands in your map?**
|
||||
|
||||
{{ if .Part2.Completed -}}
|
||||
|
||||
**Congratulations! You have completed both parts! The answer was `{{ .Part2.Solution }}`.**
|
||||
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,43 @@
|
||||
package q04
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hhhapz/codequest/models"
|
||||
"github.com/hhhapz/codequest/question"
|
||||
)
|
||||
|
||||
func TestQ04(t *testing.T) {
|
||||
u := &models.User{
|
||||
ID: "123",
|
||||
}
|
||||
|
||||
q := question.QuestionByID("island")
|
||||
|
||||
raw := q.Generate(u)
|
||||
|
||||
t.Logf("INPUT:\n\n%s\n\n", raw)
|
||||
|
||||
input := make([][]rune, 0, rows)
|
||||
|
||||
for _, row := range strings.Split(raw, "\n") {
|
||||
input = append(input, []rune(row))
|
||||
}
|
||||
|
||||
// res := solveP1(input)
|
||||
// t.Logf("part 1 result: %d", res)
|
||||
// if !q.Validate(u, question.Part1, strconv.Itoa(res)) {
|
||||
// t.Errorf("Expected question 1 part 1(%v) to be correct!", res)
|
||||
// }
|
||||
|
||||
res := solveP2(input)
|
||||
if !q.Validate(u, question.Part2, strconv.Itoa(res)) {
|
||||
t.Errorf("Expected question 2 part 2(%v) to be correct!", res)
|
||||
}
|
||||
|
||||
if q.Validate(u, question.Part1, "") {
|
||||
t.Errorf("Expected bad input to be invalid")
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package q05
|
||||
|
||||
func solveP1(nums []int) int {
|
||||
var sum int
|
||||
for _, v := range nums {
|
||||
sum += int(float64(v)/2.5 - 2)
|
||||
}
|
||||
return sum
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package q05
|
||||
|
||||
func solveP2(nums []int) int {
|
||||
var sum int
|
||||
for _, v := range nums {
|
||||
fuel := int(float64(v)/2.5 - 2)
|
||||
for fuel > 0 {
|
||||
sum += fuel
|
||||
fuel = int(float64(fuel)/2.5 - 2)
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package q05
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/hhhapz/codequest/models"
|
||||
"github.com/hhhapz/codequest/question"
|
||||
)
|
||||
|
||||
func init() {
|
||||
t := template.New("fuel")
|
||||
var err error
|
||||
t, err = t.Parse(q05Text)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
question.Register(
|
||||
&question.Question{
|
||||
ID: "fuel",
|
||||
Name: "Fuel for the Farlands",
|
||||
Text: t,
|
||||
Level: question.Level1,
|
||||
Generate: func(u *models.User) string {
|
||||
inp := generate(u)
|
||||
nums := make([]string, nums)
|
||||
for i, num := range inp {
|
||||
nums[i] = strconv.Itoa(num)
|
||||
}
|
||||
return strings.Join(nums, "\n")
|
||||
},
|
||||
Validate: func(u *models.User, part question.Part, solution string) bool {
|
||||
return Validate(u, part, solution)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
nums = 350
|
||||
)
|
||||
|
||||
func generate(u *models.User) []int {
|
||||
res := make([]int, nums)
|
||||
|
||||
r := question.UserRandom(u)
|
||||
|
||||
for i := 0; i < nums; i++ {
|
||||
if nums < 10 {
|
||||
res[i] = r.Intn(10000-200) + 200
|
||||
continue
|
||||
}
|
||||
res[i] = r.Intn(1000000-1000) + 1000
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func Validate(u *models.User, p question.Part, sol string) bool {
|
||||
inp := generate(u)
|
||||
|
||||
var n int
|
||||
switch p {
|
||||
case question.Part1:
|
||||
n = solveP1(inp)
|
||||
case question.Part2:
|
||||
n = solveP2(inp)
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
fmt.Println("submitted", u.Name, p, sol)
|
||||
fmt.Println("actual", u.Name, p, n)
|
||||
return strconv.Itoa(n) == sol
|
||||
}
|
||||
|
||||
//go:embed q05.md
|
||||
var q05Text string
|
@ -0,0 +1,68 @@
|
||||
The time has arrived and you need to pack things up and say goodbye. You are leaving for the
|
||||
Farlands, and it's.. far!
|
||||
|
||||
You plan to fly solo over the continents to make it to the Farlands. This is the first time you've
|
||||
ever flown for so long, and so you need to prepare a few things before leaving.
|
||||
|
||||
The first order of business is to determine how much fuel you're going to need to reach. To do this,
|
||||
you need the empty mass of your aircraft.
|
||||
|
||||
With the mass, you can calculate the total required fuel.
|
||||
|
||||
For each each mass, the amount of fuel can be calculated using this **formula**. Take the mass,
|
||||
divide it by 2.5, round down the result, and then subtract 2.
|
||||
|
||||
Before taking off, your friends and family have sent you hundreds of gifts, which you plan to take
|
||||
with you. You'll need to know the total amount of fuel needed for your trip.
|
||||
|
||||
Apply the formula for each item (your input), and sum them to get the total requirement.
|
||||
|
||||
### Example
|
||||
|
||||
For a mass of `18`, divide it by `2.5` and round down to get `7`, then subtract `2` to get `5` as
|
||||
the fuel requirement.
|
||||
|
||||
For a mass of `58`, divide it by `2.5` and round down to get `23`, then subtract `2` to get `21`.
|
||||
|
||||
For `2022`, the requirement is `806`
|
||||
|
||||
For `84942`, the requirement is `33974`
|
||||
|
||||
**What is the total fuel requirement for your trip?**
|
||||
|
||||
{{ if .Part1.Completed -}}
|
||||
|
||||
**Congratulations! You got Part 1 correct. Your answer was `{{ .Part1.Solution }}`.**
|
||||
|
||||
## Part 2
|
||||
|
||||
Just before you about to take off, your copilot reminded you that you completely forgot to take into
|
||||
account the extra fuel needed for the fuel you already have! Just like your parting gifts, apply the
|
||||
same **formula** on the fuel to obtain the fuel needed for the fuel.
|
||||
|
||||
So, for each gift, calculate the fuel needed, treat that fuel as the mass itself, and calculate the
|
||||
fuel needed, and repeat this process **until** your fuel requirement reaches **zero or a negative
|
||||
value**.
|
||||
|
||||
### Example
|
||||
|
||||
For a mass of `18`, divide it by `2.5` and round down to get `7`, then subtract `2` to get `5` as
|
||||
the fuel requirement. `5` divided by `2.5` gives you `1`, and subtracting `2` gives you `-1` so the
|
||||
total fuel required is still `5`.
|
||||
|
||||
For a mass of `58`, `21` fuel is used. Then, `21` needs `6` more fuel, and `6` requires no further
|
||||
fuel. The total fuel needed is `21+6 = 27`
|
||||
|
||||
For `2022`, the requirement is `806+320+126+48+17+4 = 1321`
|
||||
|
||||
Using this new formula, **what is the fuel total fuel requirements** for all the mass, but also
|
||||
including the mass of the newly added fuel?
|
||||
|
||||
> Calculate the requirements seperately, and them sum them together for each item.
|
||||
|
||||
{{ if .Part2.Completed -}}
|
||||
|
||||
**Congratulations! You have completed both parts! The answer was `{{ .Part2.Solution }}`.**
|
||||
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,44 @@
|
||||
package q05
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hhhapz/codequest/models"
|
||||
"github.com/hhhapz/codequest/question"
|
||||
)
|
||||
|
||||
func TestQ05(t *testing.T) {
|
||||
u := &models.User{
|
||||
ID: "123",
|
||||
}
|
||||
|
||||
q := question.QuestionByID("fuel")
|
||||
|
||||
raw := q.Generate(u)
|
||||
|
||||
t.Logf("INPUT:\n\n%s\n\n", raw)
|
||||
|
||||
input := make([]int, 0, nums)
|
||||
|
||||
for _, num := range strings.Split(raw, "\n") {
|
||||
n, _ := strconv.Atoi(num)
|
||||
input = append(input, n)
|
||||
}
|
||||
|
||||
res := solveP1(input)
|
||||
t.Logf("part 1 result: %d", res)
|
||||
if !q.Validate(u, question.Part1, strconv.Itoa(res)) {
|
||||
t.Errorf("Expected question 1 part 1(%v) to be correct!", res)
|
||||
}
|
||||
|
||||
res = solveP2(input)
|
||||
if !q.Validate(u, question.Part2, strconv.Itoa(res)) {
|
||||
t.Errorf("Expected question 2 part 2(%v) to be correct!", res)
|
||||
}
|
||||
|
||||
if q.Validate(u, question.Part1, "") {
|
||||
t.Errorf("Expected bad input to be invalid")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue