코드 출현 2020 - 15일차
또한 일반적으로 퍼즐에 다운로드 가능한 입력이 있을 때마다
input.txt
라는 파일에 저장합니다.15일 - 광란의 암송
문제 설명을 찾습니다HERE.
1부 - 순록 엘프 게임
1부에서는 기억력 게임을 하는 엘프가 있습니다. 숫자 목록이 주어지면 엘프들은 각 숫자를 차례로 말합니다. 목록의 끝에 도달하면 이전 차례에 말한 숫자가 이전 차례 이전에 말한 이후의 라운드 수를 말하기 시작합니다. 따라서 목록 0, 3, 6
의 경우 처음 9턴 동안 [0, 3, 6], 0, 3, 1, 0, 4, 0
를 얻습니다. 진짜 질문은 2020년 턴에 말하는 숫자는 무엇입니까?
솔직히 말해서, 아래의 구현은 이것에 대한 나의 첫 크랙이 아니지만, 나중에 명확해질 이유 때문에(또는 이러한 퍼즐이 어떻게 구성되어 있는지에 대한 아이디어를 얻기 시작한다면 더 빨리), R에서 생각해낼 수 있는 가장 빠른 구현.
library(testthat) # For tests
# Given a starting sequence `start_vec` and a number `n`, returns the `n`th
# number of the elve's counting game, according to the rules in the puzzle
# instructions. Note, the `rounds` vector below contains, at each index, the
# last round (prior to the most recent round) that the number (index - 1) was
# spoken. This is because R is 1-indexed, so the value for '0' is stored in
# index '1' and so on.
number_spoken <- function(start_vec, n) {
rounds <- numeric(0) # Empty vector for the round a number was last spoken
start_len <- length(start_vec) # Length of the `start_vec`
last_number <- start_vec[start_len] # Last number spoken, starting value
# Fill in the starting numbers into `rounds`
for (i in 1:start_len) { rounds[[start_vec[i]+1]] <- i }
# For each number after the starting veector...
for (i in (start_len+1):n) {
index <- last_number + 1 # Correction for 1-indexing
# If the `index` either contains the number of the last round or an NA,
# then the last round was the first time `last_number` was spoken and the
# `next_number` should be '0'. Otherwise, the `next_number` should be the
# number of the last round (i-1) minus the number of the previous round
# in which the number was spoken (rounds[last_number+1])
next_number <- if (is.na(rounds[index]) || rounds[index] == i - 1) {
0
} else {
(i - 1) - rounds[last_number+1]
}
rounds[last_number+1] <- i - 1 # Update the round number stored for this number
last_number <- next_number # The new `last_number` is this `next_number`
# Sanity Check
if (i %% 10000 == 0) { cat('\r', paste('Simulating round:', i)) }
}
next_number # Return the `n`th number spoken
}
test_that("sample inputs return expected results", {
expect_equal(number_spoken(c(0, 3, 6), 2020), 436)
expect_equal(number_spoken(c(1, 3, 2), 2020), 1)
expect_equal(number_spoken(c(1, 2, 3), 2020), 27)
expect_equal(number_spoken(c(2, 3, 1), 2020), 78)
expect_equal(number_spoken(c(3, 2, 1), 2020), 438)
expect_equal(number_spoken(c(3, 1, 2), 2020), 1836)
})
answer1 <- number_spoken(c(2, 0, 1, 7, 4, 14, 18), 2020)
# Answer: 496
기억이 나지 않는 이유로 이 퍼즐에 테스트를 사용하도록 영감을 받았습니다. testthat
패키지와 기능을 통해 한 번에 모두 테스트할 수 있는 쉬운 방법을 제공하기 때문에 주어진 테스트 입력의 수와 관련이 있다고 생각합니다. 알려진 엣지 케이스를 놓치지 않고 구현을 조정할 수도 있습니다.
2부 - 더!
source('exercise_1.R')
# Yep, that's it.
answer2 <- number_spoken(c( 2, 0, 1, 7, 4, 14, 18), 30000000)
구현 속도가 중요한 이유입니다.
마무리
아, 컴파일된 언어를 사용하는 사람들이 부럽기도 합니다만, 제 일상 업무가 엄청나게 빠른 배열 조회보다 shiny
대시보드와 tidyverse
의 데이터 분석을 훨씬 더 잘 활용한다는 것을 깨달았습니다. 그리고 나는 그것에서 스냅합니다. 즉, 이것은 R에서 신속하게 작업을 수행하는 방법에 대해 배울 수 있는 좋은 기회였습니다(지금까지 많은 시간을 할애하지 않은 것입니다). 간단한 요점은 벡터에 NA
가 많이 포함되어 있어도 벡터의 알려진 인덱스에서 값을 얻는 것은 매우 간단하다는 것입니다. 환경에서 키로 값을 찾는 것보다 확실히 빠르며 명명된 목록을 일종의 의사 사전으로 사용하는 것보다 훨씬 빠릅니다. 전반적으로 좋은 하루!
다른 솔루션을 찾았거나 내 솔루션 중 하나에서 실수를 발견한 경우 저에게 연락해 주세요!
Reference
이 문제에 관하여(코드 출현 2020 - 15일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/ericwburden/advent-of-code-2020-day-15-2fi6
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
library(testthat) # For tests
# Given a starting sequence `start_vec` and a number `n`, returns the `n`th
# number of the elve's counting game, according to the rules in the puzzle
# instructions. Note, the `rounds` vector below contains, at each index, the
# last round (prior to the most recent round) that the number (index - 1) was
# spoken. This is because R is 1-indexed, so the value for '0' is stored in
# index '1' and so on.
number_spoken <- function(start_vec, n) {
rounds <- numeric(0) # Empty vector for the round a number was last spoken
start_len <- length(start_vec) # Length of the `start_vec`
last_number <- start_vec[start_len] # Last number spoken, starting value
# Fill in the starting numbers into `rounds`
for (i in 1:start_len) { rounds[[start_vec[i]+1]] <- i }
# For each number after the starting veector...
for (i in (start_len+1):n) {
index <- last_number + 1 # Correction for 1-indexing
# If the `index` either contains the number of the last round or an NA,
# then the last round was the first time `last_number` was spoken and the
# `next_number` should be '0'. Otherwise, the `next_number` should be the
# number of the last round (i-1) minus the number of the previous round
# in which the number was spoken (rounds[last_number+1])
next_number <- if (is.na(rounds[index]) || rounds[index] == i - 1) {
0
} else {
(i - 1) - rounds[last_number+1]
}
rounds[last_number+1] <- i - 1 # Update the round number stored for this number
last_number <- next_number # The new `last_number` is this `next_number`
# Sanity Check
if (i %% 10000 == 0) { cat('\r', paste('Simulating round:', i)) }
}
next_number # Return the `n`th number spoken
}
test_that("sample inputs return expected results", {
expect_equal(number_spoken(c(0, 3, 6), 2020), 436)
expect_equal(number_spoken(c(1, 3, 2), 2020), 1)
expect_equal(number_spoken(c(1, 2, 3), 2020), 27)
expect_equal(number_spoken(c(2, 3, 1), 2020), 78)
expect_equal(number_spoken(c(3, 2, 1), 2020), 438)
expect_equal(number_spoken(c(3, 1, 2), 2020), 1836)
})
answer1 <- number_spoken(c(2, 0, 1, 7, 4, 14, 18), 2020)
# Answer: 496
source('exercise_1.R')
# Yep, that's it.
answer2 <- number_spoken(c( 2, 0, 1, 7, 4, 14, 18), 30000000)
Reference
이 문제에 관하여(코드 출현 2020 - 15일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/ericwburden/advent-of-code-2020-day-15-2fi6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)