Ruby 3.0의 출시 03일째 썰매 궤도
24386 단어 adventofcoderuby
이 시리즈에서는 Ruby 2.7 및 3.0의 몇 가지 기능과 사용 방법solve Advent of Code problems에 대해 설명합니다.해결 방안 자체가 가장 효과적이라는 뜻이 아니라 기능의 새로운 용도를 보여줘야 한다.
나는 이 문장들을 날짜별로 분류할 것이다. 왜냐하면 매 문장은 점점 길어지고 그 안에 관련되기 때문에 나는 10분 이상의 문장을 자주 발표하는 것을 좋아하지 않는다.
여기까지 말하고 시작합시다!
|
Day 03-제01부분-눈썰매 궤도
나는 이 점을 이해하는 데 약간의 시간이 걸렸다.우리 지도에는 나무(
#
와 공백.
:..#..#
..#..#
.#..#.
우리의 썰매는 왼쪽 상단에서 시작하는데 첫 번째 부분의 경사도1
가 3
를 초과하거나 1
방향y
방향과3
방향x
방향이다.X
는 나무가 충돌한 것을 감안하면O
은 광활한 공간이다. 우리는 우리의 썰매가 비탈길에서 활주하는 것을 볼 수 있다.O.#..#
..X..#
.#..#O
이런 상황에서 우리는 나무에 부딪혔지만, 만약 우리가 경계를 넘었다면?보아하니 그들의 지도는 무한히 중복된 것 같아서 한 선이 ..#
이면 중복된다. 예를 들어 ..#..#..#..#
등이다.솔루션부터 시작해 보겠습니다. 여기서부터 시작하겠습니다.
SLOPE = [3, 1]
SLOPE_X, SLOPE_Y = SLOPE
TREE = '#'
def collision_count(map, slope_x: SLOPE_X, slope_y: SLOPE_Y)
map_modulo = map.first.strip.size
pos_x, pos_y = 0, 0
map[1..-1].reduce(0) do |trees_hit, line|
pos_x, pos_y = pos_x + slope_x, pos_y + slope_y
relative_x = pos_x % map_modulo
line[relative_x] == TREE ? trees_hit + 1 : trees_hit
end
end
File.readlines(ARGV[0]).then { puts collision_count(_1) }
상수
처음 행에서는 기본값에 대해 몇 가지 상수만 설정하고 나중에 사용할 값의 이름을 지정합니다.
SLOPE = [3, 1]
SLOPE_X, SLOPE_Y = SLOPE
TREE = '#'
이 줄, 특히 나의 작은 습관은 상수를 kwargs와 함께 좋은 기본값으로 명명하는 데 사용한다.def collision_count(map, slope_x: SLOPE_X, slope_y: SLOPE_Y)
설정할 수 있는 곳으로 만들지만, 정상적인 명칭 기본값을 가지고 있습니다.이런 상황에서 경사율은 고정적이지만 장래에는 그렇지 않을 수도 있다. 이것은 우리가 필요할 때 조정할 수 있게 한다.모형
수학은 절대 우리의 친구, 모함수에 관한 것이다.익숙하지 않은 모드에 대해 나눗셈 후의 나머지를 제시하기 때문에 다음과 같다.
10 % 10 == 0
10 % 15 == 5
10 % 25 == 5
왜 25
안 줘요15
?10
는 깨끗하게 두 부분으로 나눌 수 있고 나머지5
와 15
는 같기 때문이다.이것은 시리즈를 순환하고 순환하는 데 매우 유용하며, 이 예에서는 무한히 오른쪽으로 뻗은 스티커입니다.이것이 바로 이 말이 왜 매우 유용한지 우리에게 단점이 어디에 있는지 알려줄 수 있다.
map_modulo = map.first.strip.size
낙하산.
이 감소를 살펴보겠습니다. 잠시 후에 우리는 재미있는 견해를 가지고 있을 것입니다.
pos_x, pos_y = 0, 0
map[1..-1].reduce(0) do |trees_hit, line|
pos_x, pos_y = pos_x + slope_x, pos_y + slope_y
relative_x = pos_x % map_modulo
line[relative_x] == TREE ? trees_hit + 1 : trees_hit
end
우선 당신은 map[1..-1]
를 주의하게 될 것입니다. 이것은 첫 번째 줄이 우리와 무관하기 때문입니다. 왜냐하면 문제에 따라 썰매는 항상 깨끗한 곳에서부터 시작하기 때문입니다.우리는 여기서 초기치
reduce
의 0
를 사용하여 우리가 불행하게 만난 나무의 총수를 누적한다.map[1..-1].reduce(0) do |trees_hit, line|
우리가 먼저 알아야 할 것은 우리의 입장이다.위의 첫 줄에서 우리는 x
와 y
를 0
로 시작 위치로 설정할 것이다.이 길드는 경사도에 따라 업데이트됩니다.pos_x, pos_y = pos_x + slope_x, pos_y + slope_y
우리는 y
위치를 실제로 사용하지 않았지만, 나는 그것이 잠시 후에 나타날 것이라고 확신한다. 그래서 우리는 범위에 따라 업데이트를 진행할 수 있다.이 부분의 진정한 문제는 우리가 무한지도상의 위치에 있다는 것이다.모형 기억나세요?우리는 그것으로 우리가 앞에서 알고 있는 지도상의 상대적인 위치를 얻을 수 있다.
relative_x = pos_x % map_modulo
그래서 만약에 우리가 x
의30
에서 출발하면 지도는 12
개 단위장만 있고 우리의 친척x
이 6
이거나 30 % 12
인 것을 알 수 있다.일단 우리가 지도에 대한 위치를 알게 되면 그곳에 나무가 있는지 물어볼 수 있다.
line[relative_x] == TREE
있는 경우 카운트에 하나를 추가하거나 현재 카운트를 반환하고 다음 행을 확인합니다.line[relative_x] == TREE ? trees_hit + 1 : trees_hit
우리 오랜 친구
이것은 아주 비슷한 선 하나만 남았다.
File.readlines(ARGV[0]).then { puts collision_count(_1) }
...우리는 우리의 해결 방안이 있다.3일째 - 2부 - 각도가 뭐예요?
위에서 우려한 바와 같이, 사율이 바뀔 수 있다.
y
의 사율을 포함해서. 이것은 간단한 교체가 더 이상 효과가 없다는 것을 의미한다.하지만 두려워하지 마세요. 루비는 이 문제를 상당히 간단하게 만들 수 있는 재미있는 기교가 있으니까요.차근차근
우리는 깨끗하게 교체할 수 없기 때문에, 우리는 반드시 다른 해결 방안을 찾아야 한다.
...아니면 우리?만약 루비에게 이런 상황을 겨냥한 도구가 있다면?이것은
step
또는 업데이트%
범위 연산자로 불린다.(1..10).step(3).to_a
# => [1, 4, 7, 10]
((1..10) % 3).to_a
# => [1, 4, 7, 10]
%
의 우선촬영..
이 범위에 적용되기 때문에 이렇게 하지 마십시오.(1..10 % 3).to_a
# => [1]
...10 % 3
는1
이기 때문에 현재의 범위는1..1
이다.어쨌든 나는
step
을 선택하는 경향이 있다. 왜냐하면 그것은 더욱 뚜렷하지만 그 존재가 매우 좋다는 것을 알고 있기 때문이다.이 모든 것을 감안하여 우리는
map
범위를 이 범위로 바꿀 수 있다. 우리는 y
가 1
보다 크다고 해석할 수 있다.map[(slope_y..map.size) % slope_y]
긁어모으다
Ruby는 이 점을 상당히 간단하게 만들었다. 우리의 주함수의 유일한 진정한 변화는 다음과 같다.
def collision_count(map, slope_x: SLOPE_X, slope_y: SLOPE_Y)
map_modulo = map.first.strip.size
pos_x, pos_y = 0, 0
map[(slope_y..map.size) % slope_y].reduce(0) do |trees_hit, line|
pos_x, pos_y = pos_x + slope_x, pos_y + slope_y
relative_x = pos_x % map_modulo
line[relative_x] == TREE ? trees_hit + 1 : trees_hit
end
end
다섯 번째 줄만 마지막에 바뀌었어, 대단해!입력
유일한 또 다른 차이점은 우리가 우리의 독선을 약간 바꾸었다는 것이다.
POSITIONS = [
{ slope_x: 1, slope_y: 1 },
{ slope_x: 3, slope_y: 1 },
{ slope_x: 5, slope_y: 1 },
{ slope_x: 7, slope_y: 1 },
{ slope_x: 1, slope_y: 2 }
]
File.readlines(ARGV[0]).then do |map|
puts POSITIONS
.map { |pos| collision_count(map, **pos) }
.reduce(1, :*)
end
우리는 위치 조정 목록을 보여 주고 지도에 비추어 우리가 성공한 나무의 수를 얻은 다음에AoC의 프로그램 규범에 따라 그것들을 모두 곱하기만 하면 된다.이제 저희가 1부와 2부를 완성했습니다!
03일째 - 병행성과 반군에 대한 추가 사고
근데 여기 재미있는 패턴이 있어요.추가 고려 사항:
0
를 어떤 숫자에 더하면 그 숫자a + b + c == (a + b) + c == a + (b + c)
1 + -1
추가 취소1
1 + 2 + 3 == 2 + 3 + 1 == 3 + 2 + 1
Wikipedia covers some of this하지만 이제 우리는 덧셈이 하나의 교환군이라는 것을 기쁘게 보게 될 것이다. 이것은 병행이 매우 쉽다는 것을 의미하기 때문이다.
x
및 y
에서 내보내기 가능우리는 우리의
slope_x
위치와 사율을 통해 상대적x
위치를 얻을 수 있다.map_boundary = map_line.size - 1
position = (y * slope_x) % map_boundary
이것은 우리가 필요로 하는 물건을 찾기 위해 엄격하게 그것들을 교체할 필요가 없다는 것을 의미한다.나무의 총 명중수를 찾는 것은 정수 덧셈이다
너는 나무 한 그루에 부딪히든지, 이것은 너에게 줄 것이다.
y
, 아니면 네가 부딪히지 않았든지, 이것은 너에게 빈 것을 줄 것이다. + 1
이것은 운행하는 모든 병렬 라인에서 한 라인이 되돌아오는지 0
또는 1
를 찾아내 주 라인의 운행 총수에 추가할 수 있다는 것을 의미한다.그렇다면 왜 아벨 그룹에 관심을 갖는 걸까?트리 클릭이 이 모드를 따르기 때문에, 이것은 우리가 비슷한 일을 할 수 있음을 의미한다. (psuedo 코드)
CPU_COUNT = 16
TREE = '#'.freeze
workers = 16.times.map do
# This is NOT valid syntax inside the ractor, will test
# later once I can talk to some folks
Ractor.new do
loop do
# For instance this will work, but...
Ractor.receive => { y:, slope_x:, map_line: }
# This will complain about non-local references
# even though they're local variables
map_boundary = map_line.size - 1
position = (y * slope_x) % map_boundary
# Then this will be annoyed at `TREE` being
# non-local despite freezing
Ractor.yield map_line[position] == TREE ? 1 : 0
end
end
end
# Ractor pipe, need to figure out syntax, reading
# through articles but rather hard to follow
worker_queue = nil
# The idea is to send lines to whatever worker, wait
# for eventual return, and sum those all up once all
# lines are processed.
map.lines.map { |line| worker_queue.send(line) }.sum
너는 심지어 노선을 바꿀 수도 있다. 우리가 경사도와 위치를 알기만 하면 된다.두 번째 부분은 당연히 일을 좀 복잡하게 만들 수 있지만 너무 복잡하지는 않을 것이다.귀신이 곡할 노릇이다.
0
이론적으로 너는 그것에 무한한 여러 개의 선을 계속 제공할 수 있다. 그것은 계속 운행할 것이다.여기에는 잠재력이 많지만 지금은 이해하기 어려워요. 그래서 이 잠재력을 계속 발휘해서 어떻게 이루어졌는지 알려드릴게요.
너는 어떤 생각이나 무엇이 그것을 작용하게 하는지 아니?트위터 @keystonelemur에서 DM을 찍어 주세요. 얘기하고 싶어요.
마감 03일
3일의 끝과 관련하여 우리는 이 문제들을 계속 연구하고, 다음 며칠과 몇 주 내에 그들의 해결 방안과 방법을 탐색할 것이다.
모든 원시 해결 방안을 찾으려면 the Github repo 전체 주석의 해결 방안을 보십시오.
|
Reference
이 문제에 관하여(Ruby 3.0의 출시 03일째 썰매 궤도), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/baweaver/advent-of-ruby-3-0-day-03-toboggan-trajectory-4e9c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)