Title: Day 1 - Advent of Code 2025
URL Source: http://adventofcode.com/2025/day/1
--- Day 1: Secret Entrance ---
The Elves have good news and bad news.
The good news is that they've discovered project management! This has given them the tools they need to prevent their usual Christmas emergency. For example, they now know that the North Pole decorations need to be finished soon so that other critical tasks can start on time.
The bad news is that they've realized they have a different emergency: according to their resource planning, none of them have any time left to decorate the North Pole!
To save Christmas, the Elves need you to finish decorating the North Pole by December 12th.
Collect stars by solving puzzles. Two puzzles will be made available on each day; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!
You arrive at the secret entrance to the North Pole base ready to start decorating. Unfortunately, the password seems to have been changed, so you can't get in. A document taped to the wall helpfully explains:
"Due to new security protocols, the password is locked in the safe below. Please see the attached document for the new combination."
The safe has a dial with only an arrow on it; around the dial are the numbers 0 through 99 in order. As you turn the dial, it makes a small click noise as it reaches each number.
The attached document (your puzzle input) contains a sequence of rotations, one per line, which tell you how to open the safe. A rotation starts with an L or R which indicates whether the rotation should be to the left (toward lower numbers) or to the right (toward higher numbers). Then, the rotation has a distance value which indicates how many clicks the dial should be rotated in that direction.
So, if the dial were pointing at 11, a rotation of R8 would cause the dial to point at 19. After that, a rotation of L19 would cause it to point at 0.
Because the dial is a circle, turning the dial left from 0 one click makes it point at 99. Similarly, turning the dial right from 99 one click makes it point at 0.
So, if the dial were pointing at 5, a rotation of L10 would cause it to point at 95. After that, a rotation of R5 could cause it to point at 0.
The dial starts by pointing at 50.
You could follow the instructions, but your recent required official North Pole secret entrance security training seminar taught you that the safe is actually a decoy. The actual password is the number of times the dial is left pointing at 0 after any rotation in the sequence.
For example, suppose the attached document contained the following rotations:
L68
L30
R48
L5
R60
L55
L1
L99
R14
L82
Following these rotations would cause the dial to move as follows:
- The dial starts by pointing at
50. - The dial is rotated
L68to point at82. - The dial is rotated
L30to point at52. - The dial is rotated
R48to point at0. - The dial is rotated
L5to point at95. - The dial is rotated
R60to point at55. - The dial is rotated
L55to point at0. - The dial is rotated
L1to point at99. - The dial is rotated
L99to point at0. - The dial is rotated
R14to point at14. - The dial is rotated
L82to point at32.
Because the dial points at 0 a total of three times during this process, the password in this example is 3.
Analyze the rotations in your attached document. What's the actual password to open the door?
Solution
Part One
I think i might be misunderstanding the left and right rotation because am thinking , if the dial starts at 50
rotating to the left 68 moves, would mean it would go from 50 backwards 68 meaning (50-68) which would be point -18 then left 30 moves meaning -15-30 giving you -48 then right 48 moves to point ay 0 then left 5 times to point at -5
actually as am typing this i realize there is no negatives on our circle its just 0 - 99 meaning -18 should be at position showing (100-18) which should be 82, and then another -30 would be 52, then right 48 would be 100 or 0 in this case
Exactly. You’ve got the key idea: the dial uses wraparound arithmetic modulo 100.
- Turning left means subtract: [ \text{new position}=(\text{old position}-\text{distance})\bmod 100 ]
- Turning right means add: [ \text{new position}=(\text{old position}+\text{distance})\bmod 100 ]
Starting at 50:
L68: 50 - 68 = -18 → 82
L30: 82 - 30 = 52
R48: 52 + 48 = 100 → 0
L5: 0 - 5 = -5 → 95
The negative values are not displayed directly. Since the dial has positions 0 through 99, subtracting below 0 wraps around:
-1 → 99
-5 → 95
-18 → 82
Similarly, 100 wraps back to 0. So the example’s movement is consistent.
$0.0102
prompt_tokens=39,879 | completion_tokens=358 | total_tokens=40,237 | cached_tokens=8,778 | reasoning_tokens=112 | cost=0.010238039999999999
a = (50 - 68)%100
a82-18 % 1008218 % 10018ok help me understand what is happening here in something like a or when we do something like -a % b
Python's % operator always returns a result with the same sign as the divisor (the right-hand side). So when you do -18 % 100, Python gives you 82, not -18.
Here's the mental model. The modulo operation finds the remainder after division, but Python defines it so that:
(a % b) is always in the range [0, b-1] when b is positive
So for -18 % 100:
- How many times does
100go into-18? It goes0times, but0 * 100 = 0is above-18. Python uses floor division, so it goes-1times instead. -1 * 100 = -100- Remainder:
-18 - (-100) = 82
In other words, Python floor-divides first, then subtracts:
a % b == a - (a // b) * b
For your case:
-18 // 100 # gives -1 (floors toward negative infinity)
-1 * 100 # gives -100
-18 - (-100) # gives 82
This is different from languages like C or Java, where % can return a negative result. Python's behavior is actually the "correct" one for modular arithmetic on a circle, which is exactly what your safe dial problem needs.
For the safe dial, this means you can always write:
position = (position - distance) % 100 # left turn
position = (position + distance) % 100 # right turn
and never worry about negatives. The % 100 wraps everything back into 0..99 automatically.
$0.0729
prompt_tokens=35,734 | completion_tokens=429 | total_tokens=36,163 | cached_tokens=2,616 | cost=0.07292855999999999
100 % 991ok help me understand what is happening here in something like a
100 % 99 is asking: "after dividing 100 by 99, what's the remainder?"
99goes into100exactly 1 time (100 // 99 = 1)1 * 99 = 99- Remainder:
100 - 99 = 1
So 100 % 99 = 1. You can think of it as: 100 is one past a full cycle of 99. If your dial went from 0 to 98 (99 positions), turning right by 100 clicks would land you 1 click past where you started.
$0.0095
prompt_tokens=36,202 | completion_tokens=151 | total_tokens=36,353 | cached_tokens=35,733 | cost=0.00948543
how does -18 % 100 give you 82, i mean isnt % supposed to return the remainder so lets me break down my understanding
-18 / 100 = -0.18, what is the remainder her
The key point is that % does not mean “divide and keep the decimal part.” It gives the remainder after choosing an integer quotient.
For Python, the quotient is chosen using floor division:
[ -18 \div 100 = -1 ]
not 0, because -1 is the greatest integer less than or equal to -0.18.
Then:
[ -18 = (-1 \times 100) + 82 ]
So the remainder is:
[ -18 % 100 = 82 ]
You can verify the relationship:
-18 == (-1 * 100) + 82
# True
A useful way to picture it is to move one full revolution backwards:
-18 + 100 = 82
Since positions on the dial repeat every 100 steps, position -18 is equivalent to position 82.
Python demonstrates this with:
-18 // 100 # -1
-18 % 100 # 82
These always satisfy:
a == (a // b) * b + (a % b)
For this case:
-18 == (-1 * 100) + 82
That is why (50 - 68) % 100 correctly gives the dial position 82.
$0.0020
prompt_tokens=40,276 | completion_tokens=380 | total_tokens=40,656 | cached_tokens=39,836 | reasoning_tokens=79 | cost=0.00201108
# 1. Basic Wraparound Addition
result_add = (85 + 20) % 100
print(result_add) # Output: 5 (105 wraps around to 5)
# 2. Basic Wraparound Subtraction (Negative Numbers)
result_sub = (15 - 30) % 100
print(result_sub) # Output: 85 (-15 cleanly wraps around to 85)
# 3. Wraparound Multiplication
result_mul = (25 * 5) % 100
print(result_mul) # Output: 25 (125 wraps around to 25)
5
85
25
Import AOC Data
from aocd.models import Puzzle
p = Puzzle(year=2025, day=1)This come from here
p<Puzzle(2025, 1) at 0x760cec135880 - Secret Entrance>p.__dict__{'year': 2025,
'day': 1,
'_user': <aocd.models.User at 0x7560a03ef4d0>,
'input_data_url': 'https://adventofcode.com/2025/day/1/input',
'submit_url': 'https://adventofcode.com/2025/day/1/answer',
'input_data_path': Path('/app/data/.config/aocd/github.rubanzasilva.5126289/2025_01_input.txt'),
'answer_a_path': Path('/app/data/.config/aocd/github.rubanzasilva.5126289/2025_01a_answer.txt'),
'answer_b_path': Path('/app/data/.config/aocd/github.rubanzasilva.5126289/2025_01b_answer.txt'),
'submit_results_path': Path('/app/data/.config/aocd/github.rubanzasilva.5126289/2025_01_post.json'),
'prose0_path': Path('/app/data/.config/aocd/prose/2025_01_prose.0.html'),
'prose1_path': Path('/app/data/.config/aocd/github.rubanzasilva.5126289/2025_01_prose.1.html'),
'prose2_path': Path('/app/data/.config/aocd/github.rubanzasilva.5126289/2025_01_prose.2.html'),
'title': 'Secret Entrance'}where does p.dict come from
Every Python object has a __dict__ attribute. It's a regular dictionary that stores the object's instance attributes - the data fields set on that specific instance.
When you do something like:
p = Puzzle(year=2025, day=1)
the Puzzle.__init__ method sets attributes on p, like self.year = 2025, self.day = 1, etc. Each of those gets stored in p.__dict__.
So p.__dict__ is just a way to see all those instance attributes at once as a dict:
p.year # 2025
p.__dict__['year'] # also 2025 — same thing
Not all objects use __dict__ though. Classes that define __slots__ skip it to save memory. But most normal classes, including Puzzle, use it.
It's handy for quick inspection when you want to see everything an object is holding without digging through dir() (which also includes methods and class-level attributes).
$0.0137
prompt_tokens=37,806 | completion_tokens=265 | total_tokens=38,071 | cached_tokens=35,661 | cost=0.013742309999999999
so p.dict can help you see an objects attributes or variables ?
Yes. p.__dict__ shows the instance attributes stored directly on the object p.
For example:
p.year
# 2025
p.__dict__["year"]
# 2025
So this:
p.__dict__
displays attributes such as year, day, title, and input_data_path.
A small distinction: these are usually called attributes, not variables. Also, __dict__ does not show everything accessible through p. It excludes methods and attributes inherited from the class. For that broader view, use:
dir(p)
$0.0106
prompt_tokens=42,299 | completion_tokens=139 | total_tokens=42,438 | cached_tokens=8,753 | cost=0.01057659
then where is 'input_data_url' coming from
input_data_url is an instance attribute created when Puzzle(...) is initialized.
When you run:
p = Puzzle(year=2025, day=1)
the Puzzle class's initialization code likely does something conceptually like:
self.input_data_url = (
f"https://adventofcode.com/{self.year}/day/{self.day}/input"
)
That produces:
"https://adventofcode.com/2025/day/1/input"
Because it is stored on self, it appears in:
p.__dict__
You can inspect it directly:
p.input_data_url
and compare it with:
p.__dict__["input_data_url"]
Both access the same value. The first uses normal attribute syntax; the second looks it up directly in the instance's attribute dictionary.
$0.0134
prompt_tokens=42,615 | completion_tokens=329 | total_tokens=42,944 | reasoning_tokens=131 | cost=0.0133767
p.examples[Example(input_data='L68\nL30\nR48\nL5\nR60\nL55\nL1\nL99\nR14\nL82', answer_a='3', answer_b=None, extra=None)]Create Input
inp = p.input_data
inp'L49\nL24\nR48\nL16\nL2\nR8\nR48\nL27\nL2\nL47\nR48\nL41\nL3\nR39\nR45\nR43\nL4\nR47\nR38\nR17\nR45\nL4\nL25\nL30\nR7\nL44\nR15\nR42\nL40\nR11\nR35\nR36\nR4\nL24\nR40\nL11\nR9\nR48\nR3\nR37\nL30\nL2\nR45\nR24\nL26\nL40\nL11\nR46\nL27\nR51\nL30\nL90\nR20\nR4\nR85\nL96\nR7\nR1\nL53\nR82\nR70\nL61\nR70\nL60\nL54\nL81\nR86\nR82\nR18\nR54\nL26\nR58\nL69\nL17\nL99\nL58\nR10\nR83\nR64\nR79\nL5\nL27\nL34\nR87\nL12\nL89\nR19\nR70\nL40\nR42\nR10\nR37\nR79\nR74\nL53\nL74\nR27\nL90\nR69\nL69\nR42\nR8\nR450\nL49\nR80\nR69\nR2\nL34\nL68\nL74\nR87\nL213\nR15\nR85\nR593\nL93\nR32\nL32\nL7\nR34\nL31\nR93\nL56\nL37\nL10\nL25\nL47\nR886\nR62\nL62\nL20\nL687\nL37\nL56\nL41\nR41\nR48\nL56\nR8\nR29\nL30\nL99\nL61\nR90\nR12\nL41\nR14\nR21\nL61\nR256\nR39\nL69\nL324\nR24\nL49\nL51\nR20\nL65\nR925\nR17\nR44\nL41\nL73\nL78\nR25\nR69\nL543\nL78\nR17\nL91\nL86\nL62\nR783\nR95\nL40\nL38\nR405\nL75\nL30\nR99\nL32\nR33\nL8\nL64\nL41\nL32\nL3\nL12\nR36\nR66\nR58\nR108\nL75\nR2\nL34\nL35\nR88\nL64\nL44\nR34\nL8\nL35\nR63\nR29\nR33\nR78\nR243\nR94\nL56\nL34\nR81\nL55\nL13\nL35\nR42\nL50\nR33\nR59\nR397\nL73\nR27\nL697\nL3\nR58\nR415\nR44\nR69\nR14\nR70\nR18\nL88\nL84\nL11\nL78\nL227\nR97\nL97\nR97\nL27\nR30\nR22\nR29\nR49\nR36\nL236\nL51\nL49\nL594\nL6\nR76\nR18\nL4\nR36\nR874\nL301\nL33\nR539\nR29\nR20\nL48\nR378\nR77\nR22\nR403\nR11\nR35\nR68\nR896\nL40\nR220\nR24\nR91\nR51\nR311\nR47\nR35\nL65\nR266\nR99\nL17\nL18\nR52\nR25\nL18\nR82\nL2\nL85\nR27\nR95\nL76\nR90\nL90\nR117\nL56\nL527\nR527\nL98\nR11\nR29\nR98\nL34\nL67\nL66\nR66\nL63\nL9\nL81\nL9\nL838\nR24\nR76\nR12\nL19\nR7\nL551\nR51\nL85\nL73\nR58\nR956\nL578\nL78\nR9\nL46\nL305\nL58\nL42\nR442\nR76\nR30\nR8\nR86\nR31\nR69\nL12\nL88\nR595\nR5\nL742\nR3\nL61\nR195\nR19\nL138\nL22\nR93\nL923\nR92\nL35\nR44\nR86\nR89\nL38\nR8\nR330\nR81\nL981\nL71\nR535\nL84\nR58\nL89\nR66\nR22\nL37\nL4\nR4\nL35\nR38\nR97\nR17\nL55\nL897\nL58\nR25\nL211\nL21\nR43\nR57\nL96\nL4\nR87\nL97\nL10\nL80\nL53\nR53\nL679\nR31\nR648\nR46\nR376\nL422\nR955\nR92\nR14\nR69\nL357\nR14\nR699\nL2\nR16\nL63\nL137\nL89\nR64\nR25\nL50\nL81\nR66\nL96\nL365\nR8\nL82\nL2\nL80\nR14\nL889\nR57\nR43\nL88\nL4\nR49\nR556\nR53\nR31\nR660\nR61\nL738\nL23\nR91\nR9\nR38\nL84\nL365\nL49\nL68\nL20\nL94\nR12\nR72\nR77\nR690\nL707\nL32\nR63\nL33\nL87\nR422\nR182\nR83\nR79\nR48\nL27\nL96\nL88\nR27\nR63\nR15\nL17\nL4\nL46\nR81\nR640\nL85\nR51\nL83\nR42\nR430\nL61\nL27\nR3\nR55\nL317\nL83\nL180\nR63\nR76\nL71\nR12\nR90\nR810\nR39\nR62\nR70\nL9\nL62\nL92\nL26\nL11\nL173\nR72\nR878\nR41\nR211\nR21\nR78\nL99\nR167\nL167\nL19\nR77\nL54\nL67\nL37\nL50\nR883\nR721\nR946\nL89\nL18\nL24\nR250\nR285\nL24\nR20\nL30\nL346\nL24\nL22\nL30\nR96\nR3\nL47\nR48\nL20\nR37\nL29\nL36\nL55\nL62\nR37\nL20\nL17\nL83\nR99\nR37\nR90\nL51\nL91\nR442\nL824\nR55\nL44\nL381\nL30\nL2\nR55\nL55\nL4\nR904\nR71\nR78\nR58\nL92\nR902\nL17\nL778\nL71\nR49\nL5\nR205\nL1\nR53\nR48\nR939\nR61\nR51\nL51\nR95\nL95\nR11\nL11\nL63\nR85\nL22\nR51\nL751\nL4\nR233\nL29\nR90\nR32\nL590\nR5\nR63\nR60\nR24\nL842\nR40\nL382\nL3\nL97\nR874\nL3\nL280\nL3\nL787\nL1\nL58\nR58\nR846\nR94\nR60\nR3\nL10\nR7\nL61\nL39\nL47\nL53\nL48\nL152\nL20\nR584\nR77\nL1\nR60\nR33\nR29\nL62\nR78\nL92\nL86\nL94\nR94\nR6\nR75\nR19\nR62\nL39\nL23\nL68\nL66\nL85\nR27\nL32\nL976\nL963\nR49\nR12\nR2\nL11\nL573\nL45\nR22\nL93\nR19\nR56\nR54\nR79\nL325\nR15\nL8\nL275\nR85\nL119\nR19\nR65\nL65\nL90\nR53\nL622\nL41\nR65\nL65\nR34\nL861\nL1\nR28\nR20\nR419\nL48\nL545\nR27\nL73\nR42\nR3\nL45\nL271\nL29\nR636\nR564\nL564\nL36\nR21\nR79\nL27\nL287\nL86\nR62\nL62\nR73\nR90\nL63\nR94\nR85\nR30\nL26\nL533\nL605\nL45\nL82\nL18\nR954\nL54\nL841\nL52\nL7\nL64\nL96\nR60\nL34\nL132\nL64\nR30\nR6\nL6\nR13\nR29\nL50\nL5\nR98\nL685\nR519\nL33\nR904\nR58\nL948\nR46\nR33\nL774\nR395\nL37\nL36\nR40\nL48\nL71\nR52\nL68\nL48\nL84\nL9\nR9\nR27\nL27\nL62\nL883\nL55\nR133\nL992\nL436\nR31\nL37\nL46\nR26\nR708\nR13\nR62\nL75\nL548\nL8\nL7\nR61\nR37\nL674\nR52\nL8\nR108\nL274\nL2\nR74\nL25\nR441\nR86\nR17\nR176\nL193\nL28\nL66\nL94\nL8\nR392\nL96\nR764\nL88\nR461\nR76\nL67\nR81\nR73\nL12\nL93\nL10\nL96\nL12\nR923\nL79\nR41\nL533\nR14\nL86\nL78\nL80\nL94\nR95\nR43\nR970\nR411\nL24\nR61\nL61\nR43\nL34\nL68\nL606\nR65\nR46\nR854\nR716\nL94\nR806\nR799\nL792\nR10\nL45\nR3\nL94\nL93\nL58\nR90\nR20\nR32\nL54\nR54\nL7\nL90\nR97\nL4\nR34\nL30\nR7\nL34\nL73\nL545\nR50\nL41\nR62\nL6\nR702\nR478\nL495\nL93\nL15\nR3\nR79\nR827\nL72\nL35\nR57\nL77\nL846\nR334\nR77\nL25\nL19\nR30\nR70\nL27\nL72\nL1\nL69\nR69\nR86\nR35\nL92\nR90\nR81\nR918\nL64\nL54\nL64\nR79\nL709\nR25\nL23\nL91\nR56\nL56\nR855\nR79\nL151\nL81\nR19\nR76\nR86\nL13\nL87\nR782\nR68\nL38\nL24\nL29\nR287\nR26\nR28\nR27\nL55\nL506\nR34\nR94\nR106\nL90\nL46\nL84\nL80\nR246\nL346\nL77\nR77\nL25\nR556\nR69\nL89\nR89\nL26\nL74\nR62\nR38\nL99\nL21\nL15\nR435\nR31\nR97\nL28\nR10\nR90\nL97\nL3\nL5\nL77\nL65\nR29\nR29\nL11\nL5\nL2\nR74\nR33\nL42\nR54\nL28\nR616\nR50\nL27\nR27\nL27\nL49\nL72\nR92\nR6\nL33\nR93\nR58\nL26\nL71\nL21\nR86\nL44\nL75\nL67\nR28\nL62\nR63\nL96\nR135\nL65\nR41\nL44\nR27\nL27\nR30\nL955\nL63\nR94\nL493\nL22\nR56\nL36\nL11\nL60\nR897\nL201\nL1\nR33\nR61\nL14\nR36\nR17\nR47\nL347\nR332\nR35\nR34\nL10\nL59\nL447\nL15\nL4\nL34\nL8\nL26\nR84\nL17\nL33\nR31\nL44\nR13\nR91\nL91\nR61\nL25\nR64\nR43\nR57\nL71\nR71\nL85\nR485\nL825\nL71\nL699\nL405\nL98\nR198\nR84\nR3\nR13\nL39\nR44\nL979\nR621\nL47\nL77\nR68\nR37\nL22\nL6\nL428\nL472\nR28\nR2\nL670\nR45\nR195\nR55\nR88\nR66\nL81\nR604\nR68\nL261\nR78\nR56\nL96\nR23\nR24\nR76\nL18\nR18\nL83\nR83\nR61\nL61\nL68\nR4\nR135\nR85\nR11\nR333\nL884\nR21\nL70\nL67\nL10\nL90\nR40\nL44\nR804\nL53\nR48\nR62\nL74\nL38\nR84\nR24\nL72\nR59\nL61\nR21\nR19\nR72\nL91\nR78\nL40\nL2\nR67\nL414\nR11\nR46\nR54\nR40\nL410\nR99\nR73\nR56\nR94\nR17\nL95\nR726\nR62\nR38\nL7\nL91\nR69\nR329\nR549\nL21\nR75\nR91\nL94\nR2\nR198\nL390\nL10\nR99\nR1\nL790\nL81\nR98\nR73\nL837\nL948\nR38\nR86\nR79\nL18\nR62\nL62\nL109\nR54\nL40\nL75\nL3\nL727\nR96\nL66\nL67\nR16\nR75\nL73\nL88\nR7\nL6\nR6\nL6\nR47\nL94\nL976\nR543\nL39\nL75\nR20\nL788\nR68\nL69\nR55\nR84\nL70\nL57\nR721\nL85\nR21\nR91\nR9\nR4\nL48\nR44\nR63\nL848\nR385\nL26\nL74\nR71\nL6\nL565\nL702\nL98\nL23\nL77\nL62\nL38\nL53\nL547\nR26\nR43\nL917\nL67\nL67\nR974\nR893\nL85\nL67\nR2\nR346\nL184\nL127\nR830\nL84\nR884\nL33\nL67\nR54\nL13\nL33\nL98\nL104\nR11\nL17\nR60\nL460\nL66\nR17\nL51\nL81\nL19\nL13\nR3\nL90\nR328\nL87\nL41\nR57\nR18\nR67\nR17\nR15\nR26\nL8\nL392\nL97\nL70\nL644\nL629\nR7\nR88\nR140\nR28\nL23\nL492\nL8\nL94\nL14\nL399\nL2\nR9\nL76\nR22\nR52\nR602\nL56\nL44\nR79\nL164\nL15\nL22\nR72\nR805\nL85\nR64\nL73\nR89\nR750\nL87\nR55\nL65\nR349\nR50\nL2\nR982\nR34\nL16\nR74\nR74\nL122\nL83\nR57\nR35\nR65\nR351\nR22\nR90\nL50\nR23\nR66\nR97\nL45\nR34\nR49\nR985\nR434\nR62\nR118\nR64\nL13\nL68\nL14\nR35\nR960\nR57\nL57\nR12\nL951\nR346\nR29\nL36\nL63\nL60\nL77\nR71\nL19\nR48\nL36\nL64\nL934\nR23\nL59\nR70\nR127\nR11\nL32\nR28\nL34\nR90\nR10\nL58\nL65\nR47\nR18\nR58\nR306\nL67\nR976\nR85\nR119\nR10\nR39\nR87\nL36\nL19\nR51\nR18\nR31\nR72\nR88\nL360\nR4\nL875\nR755\nR716\nL76\nL1\nR77\nR20\nR80\nL243\nR27\nR16\nR698\nL646\nR48\nL64\nR2\nR462\nL36\nR1\nR81\nR61\nL68\nR30\nL769\nR18\nL41\nL77\nL10\nL756\nL53\nR19\nL12\nL89\nR1\nR97\nR14\nL8\nR97\nR86\nL53\nR67\nR17\nR78\nL376\nR29\nR45\nR29\nL98\nL38\nL13\nL73\nR845\nR80\nR485\nR982\nL29\nL78\nR83\nL593\nL3\nL972\nR539\nR61\nL67\nR58\nR9\nL40\nL14\nL66\nL80\nR43\nR94\nL537\nR19\nL31\nR58\nL27\nL9\nL310\nL99\nL1\nL54\nL46\nL925\nR191\nR34\nR79\nR80\nR41\nL313\nL60\nL49\nL26\nR22\nL74\nL81\nL6\nR76\nR27\nR44\nR570\nR570\nL7\nL48\nL95\nL50\nL65\nL93\nR6\nR52\nL45\nL19\nL36\nR44\nL44\nR795\nL95\nL51\nR51\nL999\nL1\nL20\nL75\nL1\nL4\nL90\nL10\nL40\nR88\nR106\nL35\nR81\nR6\nR38\nR67\nL11\nR55\nR394\nR51\nL47\nL56\nR89\nR66\nR74\nR79\nR95\nR96\nL34\nR38\nR74\nL93\nR45\nR22\nR52\nR58\nL58\nL38\nL623\nR61\nR74\nL32\nL45\nR703\nR30\nR90\nR98\nL72\nR40\nR55\nR59\nL54\nR26\nL70\nR798\nR88\nR15\nR32\nR86\nR79\nR1\nR87\nL93\nR5\nL828\nR28\nL502\nR2\nR25\nL25\nL83\nL85\nL32\nR53\nR14\nL15\nR16\nL68\nL407\nL88\nR37\nL42\nR322\nR39\nL29\nL873\nR43\nL54\nR72\nR77\nR3\nL38\nL92\nL133\nR63\nR67\nL55\nL12\nL412\nL70\nR82\nR27\nR86\nR17\nR70\nL47\nL75\nL41\nL59\nL178\nL906\nL94\nL15\nL285\nL31\nR131\nR63\nR75\nL304\nL18\nR857\nR27\nR193\nL93\nL86\nR91\nR95\nR11\nL79\nR21\nR27\nR53\nL34\nR501\nR47\nR919\nR34\nR90\nR42\nR14\nR54\nR47\nL47\nR10\nL10\nL43\nL57\nL38\nL49\nR87\nL68\nR46\nL78\nL17\nL41\nL34\nR66\nL74\nL11\nL89\nL222\nR22\nL66\nR19\nL12\nL741\nR27\nR32\nL504\nL834\nL71\nR16\nR69\nL35\nL591\nL9\nR68\nL791\nL24\nR31\nL4\nR17\nR514\nL15\nR4\nL66\nL34\nR34\nR77\nL80\nR69\nR68\nL68\nL513\nL21\nL166\nL5\nR72\nL85\nL382\nR69\nR85\nR546\nL98\nR98\nL34\nL966\nL43\nR43\nR15\nR85\nR83\nL80\nL1\nL18\nL12\nL58\nL94\nR80\nR921\nR76\nL97\nR8\nR70\nL30\nL48\nR81\nR71\nL70\nL94\nR12\nL71\nL229\nR556\nR44\nR55\nL61\nR37\nR48\nR508\nL311\nR62\nR62\nR43\nL5\nL57\nR84\nL165\nR90\nL90\nR27\nL36\nR35\nR29\nL55\nR80\nL80\nL30\nR30\nR96\nR4\nR94\nR63\nR743\nR14\nL14\nR96\nR204\nL883\nR854\nR30\nL90\nR80\nL996\nR69\nR36\nL46\nL16\nL38\nR24\nR55\nL79\nR69\nL57\nR655\nL99\nL9\nR38\nL97\nL40\nR740\nL23\nL126\nL68\nR17\nL87\nR41\nL23\nL190\nR13\nL248\nL6\nR93\nL71\nL22\nL71\nR91\nL20\nL25\nL27\nR68\nR84\nL266\nL353\nL76\nL5\nR32\nR82\nR538\nL552\nR65\nL344\nR26\nL47\nL9\nR22\nL13\nR48\nR71\nR66\nR15\nR34\nR81\nL171\nL2\nR698\nR3\nR57\nL64\nR627\nL563\nL8\nR8\nL90\nR366\nL741\nL417\nL18\nL87\nL93\nR180\nR606\nR50\nL56\nR33\nR43\nR38\nL77\nR763\nL97\nR67\nR90\nL31\nR80\nL709\nL4\nR4\nR29\nL29\nL603\nL772\nL20\nR84\nL89\nL60\nR60\nL69\nL31\nR18\nL89\nR76\nR286\nR89\nR24\nR14\nL18\nR65\nL25\nL40\nL74\nR74\nL51\nR51\nR93\nL94\nR80\nL79\nL76\nL24\nL35\nL72\nL93\nR26\nL14\nR388\nR90\nR64\nL64\nR37\nL6\nR79\nR46\nL95\nR449\nR99\nL402\nR45\nL68\nL74\nR37\nR74\nL58\nL995\nR68\nL26\nL75\nR499\nL58\nR8\nR13\nL11\nR24\nL41\nR44\nL72\nR69\nR84\nR16\nR88\nR93\nL781\nR38\nL98\nR841\nL14\nR33\nL51\nR51\nR28\nL228\nL91\nL77\nL232\nR203\nR31\nR66\nL73\nR73\nR76\nL44\nR68\nL984\nL16\nL68\nR14\nL683\nR137\nR18\nR65\nR944\nL66\nR789\nR3\nL253\nL48\nL13\nL39\nL98\nR99\nL21\nL27\nL8\nR26\nR29\nL69\nR44\nL75\nL95\nR95\nL64\nL36\nR5\nR95\nL96\nL63\nR10\nL293\nL58\nR47\nL40\nR34\nR217\nL58\nR63\nL77\nL96\nL90\nL25\nR625\nR548\nL86\nR38\nR92\nR8\nR82\nR18\nL39\nR255\nL4\nL12\nR36\nR44\nL701\nL25\nR46\nR507\nR767\nL74\nR87\nR61\nL552\nR63\nL7\nL11\nR73\nL9\nL5\nR741\nL41\nL92\nL47\nL61\nL47\nL676\nL77\nL390\nL5\nL805\nR69\nR64\nL48\nL85\nL59\nR12\nR33\nL880\nL706\nL15\nR15\nL80\nR528\nL81\nL62\nR95\nR86\nL40\nL316\nR87\nR6\nR46\nL92\nR28\nR86\nR9\nR25\nR75\nL77\nL5\nR20\nL89\nL38\nL83\nR72\nR610\nL90\nL2\nR925\nR57\nL970\nL50\nR20\nR19\nR877\nR11\nR193\nR80\nR64\nL9\nL16\nR6\nR64\nL89\nL95\nR495\nR55\nL713\nL42\nL31\nR326\nL37\nL24\nL82\nR27\nL63\nR6\nR21\nR57\nL34\nL813\nR28\nL60\nR65\nL86\nR96\nR4\nR684\nL84\nL72\nL22\nL6\nL36\nR336\nR2\nR199\nL1\nL23\nL93\nL44\nL930\nL70\nR86\nL526\nR19\nR4\nL97\nR74\nR269\nL79\nR10\nL4\nL96\nR839\nR3\nL10\nR68\nL94\nR27\nL78\nL545\nL98\nR88\nL286\nL543\nR329\nL12\nR81\nL69\nL47\nL53\nL56\nL20\nR56\nL26\nL169\nR15\nR53\nL18\nL35\nR26\nR274\nR63\nR37\nR94\nR405\nL231\nL51\nR83\nL97\nL24\nL29\nL31\nL38\nL52\nR71\nR988\nL67\nL57\nL91\nL63\nR90\nR48\nR52\nR5\nR95\nL44\nR2\nR13\nL20\nL21\nL48\nR760\nR65\nR41\nR996\nR787\nR82\nL65\nL232\nR884\nL88\nL12\nL921\nR821\nR758\nR83\nR259\nR11\nL11\nL77\nR21\nL44\nL37\nR37\nR28\nR27\nR26\nL40\nR59\nR74\nR32\nR94\nL491\nL25\nR99\nL238\nR60\nL50\nR45\nL381\nL54\nR15\nR20\nR95\nR305\nR52\nL24\nL86\nR46\nL88\nR46\nR480\nL26\nL60\nL91\nL15\nL73\nR89\nR770\nR768\nR68\nR746\nL2\nL31\nL153\nL62\nL54\nL43\nR58\nR55\nR98\nR778\nL246\nR93\nR307\nL50\nL83\nR66\nR14\nR6\nR797\nR50\nL76\nL53\nL83\nR92\nR20\nL82\nL73\nR55\nR75\nL83\nR872\nR21\nL85\nR40\nL40\nL99\nR74\nR26\nR86\nL87\nL81\nR81\nL666\nL130\nR83\nL887\nR299\nR49\nR57\nR47\nR51\nR86\nR11\nL71\nL57\nR6\nL60\nL66\nL50\nR98\nL28\nL795\nL29\nR352\nL62\nR91\nL76\nL53\nL93\nL97\nR90\nR82\nR18\nL67\nR86\nL57\nR638\nL10\nR749\nL2\nL57\nL187\nR7\nR53\nR2\nL55\nR835\nL935\nL2\nL77\nR5\nR74\nL94\nR40\nR54\nR169\nL60\nL909\nL61\nL10\nL29\nL25\nR25\nL10\nL12\nR822\nL24\nL49\nL82\nL19\nR34\nL160\nL62\nL50\nL88\nR25\nL25\nL603\nR45\nL42\nR9\nR44\nL53\nR47\nR55\nL302\nR23\nR70\nL40\nL860\nR75\nR32\nR67\nR33\nL331\nR47\nR55\nL46\nR275\nR82\nL82\nL389\nL266\nL59\nL188\nL98\nL11\nR48\nR85\nL379\nR18\nR92\nR85\nL38\nR95\nL395\nL82\nR96\nL14\nL278\nR78\nL72\nR367\nR71\nR60\nR74\nR75\nR386\nR68\nL971\nR8\nR83\nR51\nL25\nL86\nL86\nL99\nL61\nL43\nR94\nL882\nL90\nR76\nR550\nR398\nR54\nL1\nL99\nL90\nR90\nR7\nR663\nL94\nL492\nL76\nL75\nL639\nR69\nR58\nL21\nR19\nL70\nL49\nL79\nL21\nR60\nR38\nL63\nL18\nL75\nL42\nL698\nL877\nL25\nR38\nR62\nL996\nR96\nR33\nL71\nR38\nL14\nL86\nL17\nR15\nR2\nL51\nL18\nL76\nL71\nL88\nL96\nR96\nR54\nL64\nL3\nL683\nL77\nL78\nR55\nL29\nR730\nL7\nR6\nR63\nR37\nL864\nL353\nR6\nL90\nR80\nR21\nR45\nL283\nR38\nL91\nR51\nL11\nL65\nR68\nR15\nR11\nR22\nR64\nR46\nR12\nR58\nL780\nR27\nR73\nR90\nL11\nR356\nL8\nR23\nR25\nR25\nR87\nR91\nR83\nL77\nL85\nR565\nL31\nL34\nR68\nR33\nL198\nR49\nR42\nR265\nL98\nR74\nL34\nL19\nL70\nL11\nL76\nR24\nL17\nR772\nL67\nR64\nL24\nR724\nL13\nL74\nL91\nL16\nR95\nR1\nL30\nR78\nR77\nR53\nL80\nL23\nR61\nR41\nL79\nL62\nR62\nR18\nR82\nL21\nL48\nR69\nR72\nL72\nL212\nR68\nL937\nR99\nR84\nR98\nL984\nL16\nL528\nR65\nL171\nR43\nR91\nL96\nL4\nR70\nR36\nL70\nR5\nR59\nL89\nL11\nL99\nR12\nR87\nL27\nL17\nR99\nR45\nL19\nR82\nL63\nL28\nL30\nR888\nL20\nL519\nR81\nL26\nL837\nL56\nR29\nL82\nR76\nR86\nL231\nL873\nL82\nL191\nL59\nL21\nR90\nL95\nR514\nL9\nL12\nL93\nR63\nR37\nR3\nR755\nR59\nR83\nR19\nL38\nR74\nL8\nL47\nR851\nL44\nR3\nR86\nL68\nR41\nL81\nR92\nL280\nR88\nL20\nR683\nR49\nL94\nL41\nR337\nR47\nL16\nR74\nL82\nL25\nL75\nR45\nL70\nL89\nL237\nL74\nR37\nR65\nL56\nR733\nL79\nR43\nL45\nL698\nL50\nL99\nL19\nR68\nL64\nL53\nL56\nR90\nL717\nR54\nR46\nR71\nR829\nL30\nL70\nR94\nR80\nL74\nR4\nL42\nL38\nL24\nL58\nL78\nR36\nR626\nL61\nR537\nL20\nL179\nL63\nL40\nR37\nL56\nL20\nR39\nL76\nR16\nL23\nR51\nL68\nL54\nR45\nR709\nL387\nL13\nL866\nR66\nL665\nL48\nL87\nL42\nL558\nL62\nL24\nR402\nR72\nL4\nL884\nL827\nL73\nR51\nL51\nL332\nL37\nL32\nL78\nL87\nL734\nL4\nL55\nL741\nL53\nL47\nL11\nR11\nR178\nL22\nL56\nR58\nR269\nR53\nL80\nL2\nR83\nR19\nL970\nR70\nL92\nR153\nL51\nL352\nL419\nR63\nR44\nR63\nR76\nL85\nR68\nL68\nL18\nL89\nR67\nR76\nL136\nL56\nR56\nL41\nR241\nL1\nL52\nR13\nL60\nR18\nL26\nR92\nR185\nL33\nR854\nL11\nR25\nL4\nR99\nR1\nR309\nR55\nL64\nL79\nL21\nR98\nL726\nL60\nR88\nR69\nR332\nR65\nR23\nL89\nR65\nL742\nL84\nR15\nR502\nR44\nR65\nR31\nR34\nR47\nL816\nL3\nL243\nR288\nL14\nL89\nR32\nL32\nL644\nR75\nL31\nR90\nR12\nR242\nR62\nL64\nL69\nL73\nL874\nR74\nR46\nL46\nL57\nL88\nR70\nR86\nR89\nR45\nL343\nL37\nL65\nL2\nR697\nL86\nL294\nL87\nL13\nR51\nR34\nL77\nR89\nL314\nL37\nR63\nL268\nL61\nL22\nR61\nR982\nL553\nR805\nL568\nR5\nR95\nL57\nL1\nR31\nR27\nR34\nR73\nL82\nL25\nL73\nL41\nR14\nL42\nR17\nL21\nR642\nL12\nL884\nR78\nR922\nR299\nR1\nR59\nR18\nL47\nR70\nL32\nR113\nR68\nL15\nR66\nL59\nL55\nL486\nL45\nL55\nL87\nR64\nL71\nR91\nL89\nR92\nR185\nL23\nR96\nR42\nR61\nR39\nL778\nR464\nL62\nL24\nR513\nL599\nL214\nL85\nL85\nL39\nR427\nR85\nL44\nL611\nR754\nR19\nR22\nL752\nR618\nL9\nR78\nL51\nR70\nR38\nL35\nL98\nL2\nL182\nR80\nR302\nR17\nR83\nR26\nL359\nL99\nR32\nL5\nL49\nL46\nR120\nL57\nL250\nL50\nL58\nR11\nR49\nR63\nR72\nL17\nR17\nR35\nR566\nR47\nL84\nR36\nR91\nR87\nL78\nL97\nL862\nL41\nL1\nL91\nL8\nR633\nL51\nR94\nR24\nL70\nR27\nL3\nL35\nL81\nR13\nR49\nR25\nR67\nR8\nL35\nL19\nR52\nR702\nR11\nR492\nR897\nR11\nR2\nR49\nL62\nR64\nR1\nR38\nR25\nR4\nL32\nL60\nR37\nR18\nL81\nL14\nL63\nL76\nL14\nR859\nR94\nL28\nR28\nL98\nL107\nR69\nR736\nL994\nR69\nR25\nL81\nL10\nR24\nL750\nR56\nL99\nL83\nR76\nR843\nR63\nL17\nL18\nL4\nL85\nL25\nR10\nR335\nR74\nR91\nR729\nR81\nL6\nR887\nR9\nL83\nL46\nL15\nR48\nL33\nL308\nR18\nL437\nR37\nR19\nR56\nR5\nR17\nR59\nL627\nL50\nL117\nL643\nR95\nL63\nL64\nR96\nR50\nR328\nR85\nL78\nR875\nR27\nR49\nR241\nL45\nL96\nR4\nR96\nL26\nR26\nR417\nR83\nL39\nR43\nL4\nL69\nL41\nL63\nR67\nR74\nR37\nR95\nR30\nR53\nL83\nR33\nL36\nR144\nR40\nR519\nL71\nL41\nR448\nR64\nR38\nR262\nL1\nL99\nR248\nL48\nL98\nR68\nR830\nR93\nR20\nL13\nR52\nR48\nR13\nL51\nL723\nR142\nR19\nR370\nL70\nL957\nR33\nR35\nL90\nL21\nR90\nL90\nR80\nL90\nR27\nL1\nL816\nR49\nL82\nL27\nR62\nR30\nR81\nR87\nL78\nL22\nL491\nR86\nR439\nR276\nR90\nL48\nL50\nR798\nR42\nR346\nL42\nR34\nL72\nL8\nL98\nL24\nR92\nL70\nR48\nR41\nL51\nR62\nL80\nL685\nR78\nR35\nL830\nL218\nR23\nL991\nR98\nL130\nL76\nL81\nL30\nR87\nR426\nR874\nL15\nL85\nR3\nL236\nR33\nL69\nL41\nL17\nL73\nL336\nL64\nR16\nL704\nL312\nR41\nL24\nR89\nR89\nR86\nR62\nL143\nL8\nL99\nR715\nR33\nR59\nR934\nL35\nR32\nR69\nR69\nR62\nR45\nL76\nR121\nL27\nL48\nL22\nR359\nR17\nR67\nR52\nL41\nR91\nR24\nR96\nL9\nR79\nR41\nR36\nR808\nR261\nR93\nR74\nR928\nR46\nR184\nL88\nR69\nR889\nR78\nR11\nL256\nL44\nL74\nL15\nL40\nR840\nR33\nR67\nR84\nL48\nL39\nR484\nR198\nR21\nR66\nR61\nL81\nL42\nR890\nR406\nR12\nR89\nL601\nL29\nL92\nR401\nR97\nL38\nR18\nR81\nR984\nL47\nR98\nR4\nL66\nR89\nR46\nL46\nL30\nL84\nL86\nR67\nL81\nL86\nL78\nR78\nL61\nL30\nR72\nR22\nR70\nR27\nR29\nR271\nR68\nL68\nR20\nR80\nR90\nR5\nR5\nR36\nR75\nR10\nL28\nR99\nR41\nL33\nL66\nL334\nR39\nL39\nL37\nL13\nR87\nR963\nR99\nL10\nR3\nR8\nL34\nL66\nR80\nL93\nR11\nL98\nL83\nL19\nL98\nR61\nR143\nR79\nL35\nR952\nR16\nR84\nR145\nL66\nR21\nL874\nL26\nR39\nL48\nL46\nR55\nL10\nR79\nR31\nL52\nL348\nR9\nL916\nL93\nR51\nL16\nR65\nR12\nL16\nR60\nR44\nR38\nR96\nR66\nR3\nL60\nR78\nL21\nR32\nR37\nL72\nL80\nR1\nL61\nL414\nL53\nR879\nR48\nL60\nR98\nR45\nL52\nL60\nL97\nL39\nR84\nL45\nR9\nL6\nR78\nL32\nL86\nR71\nL66\nL69\nR710\nL49\nL23\nL54\nL74\nL36\nL90\nL174\nL35\nL34\nR37\nR48\nR84\nL46\nL14\nL27\nR63\nR738\nL14\nL968\nR99\nL60\nL71\nL93\nL193\nL14\nR77\nL703\nR42\nR84\nR19\nL83\nL54\nL298\nL98\nR46\nR26\nR42\nL60\nL56\nL984\nL24\nL26\nL50\nL894\nL6\nL51\nL49\nL55\nL45\nR499\nR40\nR61\nR43\nL43\nR788\nR20\nR72\nR22\nR91\nL93\nL70\nR70\nL83\nR99\nL16\nL95\nL34\nL49\nL739\nL83\nR420\nL98\nR813\nR59\nL95\nR1\nR503\nL73\nR28\nR42\nL19\nL81\nR36\nL15\nR50\nR29\nR87\nL9\nL51\nL52\nR14\nL61\nL1\nR163\nL62\nR95\nR77\nL544\nR44\nR86\nL397\nL89\nL624\nL35\nL459\nL82\nL81\nL19\nL43\nL99\nL58\nR22\nR21\nL441\nR98\nL489\nR89\nR69\nR52\nR79\nL82\nR74\nL69\nL23\nR85\nL385\nR26\nL516\nR90\nL33\nR81\nR6\nR13\nR33\nR28\nL56\nR27\nR20\nL39\nR20\nR54\nL54\nL57\nL43\nR40\nL40\nL79\nL60\nL61\nR721\nR87\nL408\nR21\nR79\nL79\nR281\nL40\nL69\nL10\nL30\nR503\nL56\nL54\nR45\nL91\nR94\nR93\nR41\nR42\nL7\nR645\nL243\nL404\nR11\nL67\nR395\nR43\nL4\nR61\nR588\nR8\nL96\nR970\nR130\nL932\nR25\nR9\nL10\nL992\nL68\nL54\nL56\nL322\nL48\nL52\nL11\nL26\nR52\nR85\nR940\nL36\nR96\nL37\nL63\nR90\nL27\nL24\nR46\nL30\nR745\nL432\nL56\nL55\nR43\nL88\nR64\nL510\nR79\nR58\nR59\nL11\nL62\nR63\nL52\nR46\nR23\nR39\nL8\nL67\nR19\nL87\nR68\nL12\nL82\nR63\nL2\nR27\nL827\nR7\nL775\nL32\nL70\nR70\nL48\nL129\nR54\nL77\nR34\nL34\nL69\nR568\nL8\nR38\nR1\nL30\nR732\nL14\nL630\nR12\nL92\nL8\nR58\nR92\nR50\nL36\nL25\nL39\nR524\nL24\nR323\nL87\nR634\nR93\nR33\nR89\nL26\nL59\nL60\nR60\nR13\nR64\nR52\nR59\nR412\nR103\nR67\nR10\nL9\nR544\nR20\nL35\nR715\nL21\nR6\nL54\nR54\nL28\nR83\nL55\nL29\nL902\nL71\nL73\nL23\nL82\nR232\nR30\nR52\nR66\nR64\nL79\nR15\nR1\nL79\nR512\nR90\nL24\nR20\nL20\nR34\nL34\nL462\nR74\nL13\nR64\nL652\nR59\nL70\nL22\nL5\nL773\nR5\nR842\nL647\nR69\nR31\nR33\nL62\nR49\nL20\nR45\nL43\nR378\nL74\nR79\nL94\nL91\nL80\nR3\nR67\nR87\nR35\nR99\nL11\nL992\nL24\nR105\nR93\nL475\nR18\nR39\nL64\nR89\nR121\nR19\nL85\nL16\nL28\nL10\nR610\nR80\nR55\nR73\nR84\nR1\nL93\nL64\nR564\nL783\nR244\nR13\nL97\nR28\nR9\nL14\nL63\nR89\nL369\nL26\nR769\nL584\nL16\nR69\nR75\nL44\nL13\nR378\nR35\nR134\nR8\nR58\nL14\nL25\nL98\nL151\nL12\nR52\nL973\nL464\nR85\nL259\nL17\nL24\nL59\nR69\nR353\nR37\nL76\nR76\nL525\nR10\nL48\nL9\nR72\nL4\nL1\nL20\nL492\nR119\nL30\nR515\nR39\nR87\nR87\nL446\nR36\nR77\nR33\nR95\nL64\nL31\nL13\nL23\nR7\nR29\nR89\nL76\nL13\nL87\nR94\nR93\nL77\nL23\nR37\nR94\nR32\nR20\nR44\nL93\nR66\nL89\nR5\nL16\nL49\nL93\nL65\nL47\nL46\nR75\nR25\nL25\nL31\nL74\nL514\nL56\nR885\nL85\nL94\nR65\nR29\nL92\nR9\nL194\nL67\nR44\nR22\nR664\nR14\nR47\nR53\nL39\nL26\nL37\nR2\nL56\nL244\nL43\nL420\nL37\nL90\nL99\nL11\nR37\nL70\nR33\nL53\nR53\nL95\nR97\nR98\nR16\nR89\nL36\nL69\nL54\nR40\nR14\nR34\nR56\nL44\nL18\nR38\nL66\nR35\nR65\nL77\nR77\nL20\nR34\nR86\nR12\nR58\nR50\nL58\nR91\nR47\nR94\nL1\nL93\nR66\nR99\nL79\nR15\nL41\nL60\nL32\nR32\nR63\nL33\nL70\nR81\nR39\nL3\nR38\nL7\nL14\nL46\nR24\nR11\nR9\nR48\nL35\nL15\nR3\nL20\nL6\nR41\nL38\nL40\nR35\nL39\nL49\nR48\nR4\nR4\nL4\nL49\nL47\nL32\nR29\nL30\nL48\nL33\nR19\nL25\nL32\nL49\nR32\nR15\nR25\nR23\nR2\nR30\nR9\nL38\nR27\nR6\nR17\nL19\nR42\nR48\nR39'split_inp = inp.splitlines()
split_inp['L49',
'L24',
'R48',
'L16',
'L2',
'R8',
'R48',
'L27',
'L2',
'L47',
'R48',
'L41',
'L3',
'R39',
'R45',
'R43',
'L4',
'R47',
'R38',
'R17',
'R45',
'L4',
'L25',
'L30',
'R7',
'L44',
'R15',
'R42',
'L40',
'R11',
'R35',
'R36',
'R4',
'L24',
'R40',
'L11',
'R9',
'R48',
'R3',
'R37',
'L30',
'L2',
'R45',
'R24',
'L26',
'L40',
'L11',
'R46',
'L27',
'R51',
'L30',
'L90',
'R20',
'R4',
'R85',
'L96',
'R7',
'R1',
'L53',
'R82',
'R70',
'L61',
'R70',
'L60',
'L54',
'L81',
'R86',
'R82',
'R18',
'R54',
'L26',
'R58',
'L69',
'L17',
'L99',
'L58',
'R10',
'R83',
'R64',
'R79',
'L5',
'L27',
'L34',
'R87',
'L12',
'L89',
'R19',
'R70',
'L40',
'R42',
'R10',
'R37',
'R79',
'R74',
'L53',
'L74',
'R27',
'L90',
'R69',
'L69',
'R42',
'R8',
'R450',
'L49',
'R80',
'R69',
'R2',
'L34',
'L68',
'L74',
'R87',
'L213',
'R15',
'R85',
'R593',
'L93',
'R32',
'L32',
'L7',
'R34',
'L31',
'R93',
'L56',
'L37',
'L10',
'L25',
'L47',
'R886',
'R62',
'L62',
'L20',
'L687',
'L37',
'L56',
'L41',
'R41',
'R48',
'L56',
'R8',
'R29',
'L30',
'L99',
'L61',
'R90',
'R12',
'L41',
'R14',
'R21',
'L61',
'R256',
'R39',
'L69',
'L324',
'R24',
'L49',
'L51',
'R20',
'L65',
'R925',
'R17',
'R44',
'L41',
'L73',
'L78',
'R25',
'R69',
'L543',
'L78',
'R17',
'L91',
'L86',
'L62',
'R783',
'R95',
'L40',
'L38',
'R405',
'L75',
'L30',
'R99',
'L32',
'R33',
'L8',
'L64',
'L41',
'L32',
'L3',
'L12',
'R36',
'R66',
'R58',
'R108',
'L75',
'R2',
'L34',
'L35',
'R88',
'L64',
'L44',
'R34',
'L8',
'L35',
'R63',
'R29',
'R33',
'R78',
'R243',
'R94',
'L56',
'L34',
'R81',
'L55',
'L13',
'L35',
'R42',
'L50',
'R33',
'R59',
'R397',
'L73',
'R27',
'L697',
'L3',
'R58',
'R415',
'R44',
'R69',
'R14',
'R70',
'R18',
'L88',
'L84',
'L11',
'L78',
'L227',
'R97',
'L97',
'R97',
'L27',
'R30',
'R22',
'R29',
'R49',
'R36',
'L236',
'L51',
'L49',
'L594',
'L6',
'R76',
'R18',
'L4',
'R36',
'R874',
'L301',
'L33',
'R539',
'R29',
'R20',
'L48',
'R378',
'R77',
'R22',
'R403',
'R11',
'R35',
'R68',
'R896',
'L40',
'R220',
'R24',
'R91',
'R51',
'R311',
'R47',
'R35',
'L65',
'R266',
'R99',
'L17',
'L18',
'R52',
'R25',
'L18',
'R82',
'L2',
'L85',
'R27',
'R95',
'L76',
'R90',
'L90',
'R117',
'L56',
'L527',
'R527',
'L98',
'R11',
'R29',
'R98',
'L34',
'L67',
'L66',
'R66',
'L63',
'L9',
'L81',
'L9',
'L838',
'R24',
'R76',
'R12',
'L19',
'R7',
'L551',
'R51',
'L85',
'L73',
'R58',
'R956',
'L578',
'L78',
'R9',
'L46',
'L305',
'L58',
'L42',
'R442',
'R76',
'R30',
'R8',
'R86',
'R31',
'R69',
'L12',
'L88',
'R595',
'R5',
'L742',
'R3',
'L61',
'R195',
'R19',
'L138',
'L22',
'R93',
'L923',
'R92',
'L35',
'R44',
'R86',
'R89',
'L38',
'R8',
'R330',
'R81',
'L981',
'L71',
'R535',
'L84',
'R58',
'L89',
'R66',
'R22',
'L37',
'L4',
'R4',
'L35',
'R38',
'R97',
'R17',
'L55',
'L897',
'L58',
'R25',
'L211',
'L21',
'R43',
'R57',
'L96',
'L4',
'R87',
'L97',
'L10',
'L80',
'L53',
'R53',
'L679',
'R31',
'R648',
'R46',
'R376',
'L422',
'R955',
'R92',
'R14',
'R69',
'L357',
'R14',
'R699',
'L2',
'R16',
'L63',
'L137',
'L89',
'R64',
'R25',
'L50',
'L81',
'R66',
'L96',
'L365',
'R8',
'L82',
'L2',
'L80',
'R14',
'L889',
'R57',
'R43',
'L88',
'L4',
'R49',
'R556',
'R53',
'R31',
'R660',
'R61',
'L738',
'L23',
'R91',
'R9',
'R38',
'L84',
'L365',
'L49',
'L68',
'L20',
'L94',
'R12',
'R72',
'R77',
'R690',
'L707',
'L32',
'R63',
'L33',
'L87',
'R422',
'R182',
'R83',
'R79',
'R48',
'L27',
'L96',
'L88',
'R27',
'R63',
'R15',
'L17',
'L4',
'L46',
'R81',
'R640',
'L85',
'R51',
'L83',
'R42',
'R430',
'L61',
'L27',
'R3',
'R55',
'L317',
'L83',
'L180',
'R63',
'R76',
'L71',
'R12',
'R90',
'R810',
'R39',
'R62',
'R70',
'L9',
'L62',
'L92',
'L26',
'L11',
'L173',
'R72',
'R878',
'R41',
'R211',
'R21',
'R78',
'L99',
'R167',
'L167',
'L19',
'R77',
'L54',
'L67',
'L37',
'L50',
'R883',
'R721',
'R946',
'L89',
'L18',
'L24',
'R250',
'R285',
'L24',
'R20',
'L30',
'L346',
'L24',
'L22',
'L30',
'R96',
'R3',
'L47',
'R48',
'L20',
'R37',
'L29',
'L36',
'L55',
'L62',
'R37',
'L20',
'L17',
'L83',
'R99',
'R37',
'R90',
'L51',
'L91',
'R442',
'L824',
'R55',
'L44',
'L381',
'L30',
'L2',
'R55',
'L55',
'L4',
'R904',
'R71',
'R78',
'R58',
'L92',
'R902',
'L17',
'L778',
'L71',
'R49',
'L5',
'R205',
'L1',
'R53',
'R48',
'R939',
'R61',
'R51',
'L51',
'R95',
'L95',
'R11',
'L11',
'L63',
'R85',
'L22',
'R51',
'L751',
'L4',
'R233',
'L29',
'R90',
'R32',
'L590',
'R5',
'R63',
'R60',
'R24',
'L842',
'R40',
'L382',
'L3',
'L97',
'R874',
'L3',
'L280',
'L3',
'L787',
'L1',
'L58',
'R58',
'R846',
'R94',
'R60',
'R3',
'L10',
'R7',
'L61',
'L39',
'L47',
'L53',
'L48',
'L152',
'L20',
'R584',
'R77',
'L1',
'R60',
'R33',
'R29',
'L62',
'R78',
'L92',
'L86',
'L94',
'R94',
'R6',
'R75',
'R19',
'R62',
'L39',
'L23',
'L68',
'L66',
'L85',
'R27',
'L32',
'L976',
'L963',
'R49',
'R12',
'R2',
'L11',
'L573',
'L45',
'R22',
'L93',
'R19',
'R56',
'R54',
'R79',
'L325',
'R15',
'L8',
'L275',
'R85',
'L119',
'R19',
'R65',
'L65',
'L90',
'R53',
'L622',
'L41',
'R65',
'L65',
'R34',
'L861',
'L1',
'R28',
'R20',
'R419',
'L48',
'L545',
'R27',
'L73',
'R42',
'R3',
'L45',
'L271',
'L29',
'R636',
'R564',
'L564',
'L36',
'R21',
'R79',
'L27',
'L287',
'L86',
'R62',
'L62',
'R73',
'R90',
'L63',
'R94',
'R85',
'R30',
'L26',
'L533',
'L605',
'L45',
'L82',
'L18',
'R954',
'L54',
'L841',
'L52',
'L7',
'L64',
'L96',
'R60',
'L34',
'L132',
'L64',
'R30',
'R6',
'L6',
'R13',
'R29',
'L50',
'L5',
'R98',
'L685',
'R519',
'L33',
'R904',
'R58',
'L948',
'R46',
'R33',
'L774',
'R395',
'L37',
'L36',
'R40',
'L48',
'L71',
'R52',
'L68',
'L48',
'L84',
'L9',
'R9',
'R27',
'L27',
'L62',
'L883',
'L55',
'R133',
'L992',
'L436',
'R31',
'L37',
'L46',
'R26',
'R708',
'R13',
'R62',
'L75',
'L548',
'L8',
'L7',
'R61',
'R37',
'L674',
'R52',
'L8',
'R108',
'L274',
'L2',
'R74',
'L25',
'R441',
'R86',
'R17',
'R176',
'L193',
'L28',
'L66',
'L94',
'L8',
'R392',
'L96',
'R764',
'L88',
'R461',
'R76',
'L67',
'R81',
'R73',
'L12',
'L93',
'L10',
'L96',
'L12',
'R923',
'L79',
'R41',
'L533',
'R14',
'L86',
'L78',
'L80',
'L94',
'R95',
'R43',
'R970',
'R411',
'L24',
'R61',
'L61',
'R43',
'L34',
'L68',
'L606',
'R65',
'R46',
'R854',
'R716',
'L94',
'R806',
'R799',
'L792',
'R10',
'L45',
'R3',
'L94',
'L93',
'L58',
'R90',
'R20',
'R32',
'L54',
'R54',
'L7',
'L90',
'R97',
'L4',
'R34',
'L30',
'R7',
'L34',
'L73',
'L545',
'R50',
'L41',
'R62',
'L6',
'R702',
'R478',
'L495',
'L93',
'L15',
'R3',
'R79',
'R827',
'L72',
'L35',
'R57',
'L77',
'L846',
'R334',
'R77',
'L25',
'L19',
'R30',
'R70',
'L27',
'L72',
'L1',
'L69',
'R69',
'R86',
'R35',
'L92',
'R90',
'R81',
'R918',
'L64',
'L54',
'L64',
'R79',
'L709',
'R25',
'L23',
'L91',
'R56',
'L56',
'R855',
'R79',
'L151',
'L81',
'R19',
'R76',
'R86',
'L13',
'L87',
'R782',
'R68',
'L38',
'L24',
'L29',
'R287',
'R26',
'R28',
'R27',
'L55',
'L506',
'R34',
'R94',
'R106',
'L90',
'L46',
'L84',
'L80',
'R246',
'L346',
'L77',
'R77',
'L25',
'R556',
'R69',
'L89',
'R89',
'L26',
'L74',
'R62',
'R38',
'L99',
'L21',
'L15',
'R435',
'R31',
'R97',
'L28',
'R10',
'R90',
'L97',
'L3',
'L5',
'L77',
'L65',
'R29',
'R29',
'L11',
'L5',
'L2',
'R74',
'R33',
'L42',
'R54',
'L28',
'R616',
'R50',
'L27',
'R27',
'L27',
'L49',
'L72',
'R92',
'R6',
'L33',
'R93',
'R58',
'L26',
'L71',
'L21',
'R86',
'L44',
'L75',
'L67',
'R28',
'L62',
'R63',
'L96',
'R135',
'L65',
'R41',
'L44',
'R27',
'L27',
'R30',
'L955',
'L63',
'R94',
'L493',
'L22',
'R56',
'L36',
'L11',
'L60',
'R897',
'L201',
'L1',
'R33',
'R61',
'L14',
'R36',
'R17',
...]type(split_inp)listok so given the problem description whats next
You've got the list of rotation strings. Next steps, conceptually:
1. Parse each instruction. Each string like 'L49' splits into two parts: the first character is the direction, everything after is the distance (as an int). Think about how you'd get both from a single string.
s = 'L49'
s[0] # direction
s[1:] # distance as a string, needs int()
2. Simulate the dial. You need two pieces of state:
pos, starting at 50- a counter for how many times you land on 0
Then loop over the instructions, updating pos with the mod-100 arithmetic you worked out, and incrementing the counter whenever pos == 0 after a move.
3. Return the counter.
Before writing the full loop, try step 1 on a single instruction. Can you write an expression that turns 'L49' into the new position from a starting pos of 50?
$0.8760
prompt_tokens=100,249 | completion_tokens=386 | total_tokens=100,635 | cache_creation_tokens=58,499 | cost=0.876028125
should i now split my L/R from the following digits, maybe replace L with a negative - and R with a positive+
Yes, that’s a good simplification. Treat each rotation as a signed movement:
Rmeans positiveLmeans negative
But rather than literally replacing "L" with "-" in the string, parse the direction and distance separately:
rotation = 'L49'
direction = rotation[0] # 'L'
distance = int(rotation[1:]) # 49
move = distance if direction == 'R' else -distance
For 'L49', move becomes -49. Then update the dial with:
pos = (pos + move) % 100
Starting from 50:
pos = (50 + (-49)) % 100
# 1
This gives you one uniform update rule for both directions. The next step is applying this logic to every item in split_inp and counting whenever pos == 0.
$0.0233
prompt_tokens=83,721 | completion_tokens=289 | total_tokens=84,010 | cached_tokens=8,778 | reasoning_tokens=80 | cost=0.02326644
p.examples[0].input_data'L68\nL30\nR48\nL5\nR60\nL55\nL1\nL99\nR14\nL82'ex = (p.examples[0].input_data).splitlines()
print(ex)['L68', 'L30', 'R48', 'L5', 'R60', 'L55', 'L1', 'L99', 'R14', 'L82']
type(ex)listSplitting direction L and distance which is an int
init_pos = 50
count = 0
for i in ex:
direction = i[0]
distance = int(i[1:])
print(direction, distance)L 68
L 30
R 48
L 5
R 60
L 55
L 1
L 99
R 14
L 82
distance only print the first character from i[1], why is that
i[1:] does not mean “the character at position 1 only.” The colon means “from position 1 to the end.”
For example:
i = 'L68'
i[0] # 'L' first character
i[1] # '6' character at index 1 only
i[1:] # '68' everything from index 1 onward
Python uses zero-based indexing:
'L68'
012
So:
i[0]is'L'i[1]is'6'i[2]is'8'i[1:]is'68'
That is why this works:
distance = int(i[1:])
It takes all the digits after the direction and converts them from text to a number:
int('68') # 68
If you used i[1] instead, you would only get '6', which would incorrectly ignore the 8.
$0.0258
prompt_tokens=84,277 | completion_tokens=304 | total_tokens=84,581 | reasoning_tokens=62 | cost=0.025830299999999997
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
print(direction, distance)L 68
L 30
R 48
L 5
R 60
L 55
L 1
L 99
R 14
L 82
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
print(distance)68
30
48
5
60
55
1
99
14
82
Direction
Getting the direction to move in ie is L represents -ve while R represents +ve
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
print(move)-1
-1
1
-1
1
-1
-1
-1
1
-1
Final Position
Calculating the final position for the list of distances
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)-init_pos)%100)
print(init_pos)82
88
60
35
25
20
79
22
92
26
(-68-50)%10082(-68-50)-118(-68-50)%100(50+(-68))%10082(-30-82)%10088ok so something is wrong, if it moves anticlockwise -68 from 50 to position 82, and next -30 its should end up in position 52, why is my above not doing that
The problem is this line:
init_pos = (((move * distance) - init_pos) % 100)
You are subtracting the current position from the movement. The dial should instead start from its current position, then add the signed movement:
init_pos = (init_pos + move * distance) % 100
For the first two rotations:
Start: 50
L68:
move = -1
distance = 68
new position = (50 + (-1 * 68)) % 100
= -18 % 100
= 82
L30:
new position = (82 + (-1 * 30)) % 100
= -?
More explicitly:
(82 - 30) % 100
# 52
So your loop should currently be:
init_pos = 50
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
else:
move = 1
init_pos = (init_pos + move * distance) % 100
print(init_pos)
The first positions should then be:
82
52
0
95
55
0
99
0
14
32
Your original formula happened to produce 82 for the first rotation, but only by coincidence. The correct pattern is:
new_position = (old_position + movement) % 100
$0.0239
prompt_tokens=85,211 | completion_tokens=419 | total_tokens=85,630 | cached_tokens=8,778 | reasoning_tokens=78 | cost=0.02394744
i dont understand your explanation above
The key idea is: init_pos already tells you where the dial currently is. Each rotation should adjust that position.
Your code currently does this:
init_pos = (move * distance - init_pos) % 100
That means:
movement minus current position
But we need:
current position plus movement
So use:
init_pos = (init_pos + move * distance) % 100
Walk through the first two rotations:
Starting position: 50
First instruction: L68
move = -1
distance = 68
init_pos = (50 + (-1 * 68)) % 100
= (50 - 68) % 100
= -18 % 100
= 82
Now init_pos has been updated to 82.
Second instruction: L30
init_pos = (82 + (-1 * 30)) % 100
= (82 - 30) % 100
= 52
The important distinction is:
# Correct: current position plus signed movement
init_pos + move * distance
not:
# Incorrect: signed movement minus current position
move * distance - init_pos
A useful sentence to remember is:
Start at the current position, move left or right by the required distance, then use
% 100to wrap around the dial.
$0.0240
prompt_tokens=85,859 | completion_tokens=367 | total_tokens=86,226 | cached_tokens=8,778 | reasoning_tokens=44 | cost=0.02404824
yes explain to me why this order and not the other
The order comes from what the numbers mean:
init_pos= where the dial currently ismove * distance= how far to move from there
So the natural calculation is:
new_position = current_position + movement
For the first instruction, L68:
current_position = 50
movement = -68
Therefore:
50 + (-68)
This means:
Start at 50, then move 68 places to the left.
That gives:
50 + (-68) = -18
-18 % 100 = 82
For the next instruction, L30, the current position is now 82:
82 + (-30) = 52
The important point is that the movement is applied to the current position.
Your original expression was:
move * distance - init_pos
For L68, that becomes:
-68 - 50 = -118
This means:
Start with the movement
-68, then subtract the position50.
That is not what a dial rotation means. The position is not something to subtract from the movement; it is the starting point from which the movement occurs.
Compare them with positive numbers:
# Correct
50 + 68
# 118, which wraps to 18
This means: start at 50 and move right 68.
# Incorrect
68 - 50
# 18
This happens to give the same result in this particular case, but it is coincidence. With a left movement:
# Correct
50 + (-68)
# -18 → 82
# Incorrect
-68 - 50
# -118 → 82
Both happen to wrap to 82 too, which can hide the error. But after the first move, the formulas diverge because the current position has changed.
The reliable model is always:
new_position = (old_position + signed_movement) % 100
where:
signed_movement = -distance # L
signed_movement = distance # R
$0.0037
prompt_tokens=86,249 | completion_tokens=568 | total_tokens=86,817 | cached_tokens=85,816 | reasoning_tokens=81 | cost=0.00372678
(82+(-30))%100
52init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
print(init_pos)82
52
0
95
55
0
99
0
14
32
Getting the count
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
print(count)1
2
3
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
print(count)3
Count for actual input_data in split_inp
init_pos = 50
count = 0
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
print(count)984
Define a function
Ok so part 1 is solved, I guess now ill just put the solution in a function where i can pass any list
def zeros_count(dd_list: list[str]) -> int:
"""
zeros_count takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times 0 appears which is the password
"""
init_pos = 50
count = 0
for i in dd_list:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
# init_pos = ((init_pos + (move*distance))%100)
if init_pos == 0:
count += 1
return countzeros_count(split_inp)984zeros_count??def zeros_count(dd_list: list[str]) -> int:
"""
zeros_count takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times 0 appears which is the password
"""
init_pos = 50
count = 0
for i in dd_list:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
return count
File: /tmp/ipymini_153/3726142488.py; line: 1
zeros_count?def zeros_count(
dd_list:list
)->int:
"
zeros_count takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times 0 appears which is the password
"
File: /tmp/ipymini_153/3726142488.py; line: 1
Type: function
Potential Improvements
Replacing if / elif
From here i notice we can probably make our code more efficient by replacing the if and elif in our zeros_count function with something else like a dictionary
init_pos = 50
count = 0
moves = {"L":-1, "R":1}
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
move = moves[direction]
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
print(count)def zeros_count(dd_list: list[str]) -> int:
"""
zeros_count takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times 0 appears which is the password
"""
init_pos = 50
count = 0
moves = {"L":-1, "R":1}
for i in dd_list:
#for i in ex:
direction = i[0]
distance = int(i[1:])
move = moves[direction]
init_pos = (((move*distance)+init_pos)%100)
# init_pos = ((init_pos + (move*distance))%100)
if init_pos == 0:
count += 1
return countzeros_count(split_inp)984Part Two
You're sure that's the right password, but the door won't open. You knock, but nobody answers. You build a snowman while you think.
As you're rolling the snowballs for your snowman, you find another security document that must have fallen into the snow:
"Due to newer security protocols, please use password method 0x434C49434B until further notice."
You remember from the training seminar that "method 0x434C49434B" means you're actually supposed to count the number of times any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one.
Following the same rotations as in the above example, the dial points at zero a few extra times during its rotations:
The dial starts by pointing at 50. The dial is rotated L68 to point at 82; during this rotation, it points at 0 once. The dial is rotated L30 to point at 52. The dial is rotated R48 to point at 0. The dial is rotated L5 to point at 95. The dial is rotated R60 to point at 55; during this rotation, it points at 0 once. The dial is rotated L55 to point at 0. The dial is rotated L1 to point at 99. The dial is rotated L99 to point at 0. The dial is rotated R14 to point at 14. The dial is rotated L82 to point at 32; during this rotation, it points at 0 once. In this example, the dial points at 0 three times at the end of a rotation, plus three more times during a rotation. So, in this example, the new password would be 6.
Be careful: if the dial were pointing at 50, a single rotation like R1000 would cause the dial to point at 0 ten times before returning back to 50!
Using password method 0x434C49434B, what is the password to open the door?
ideas
- create a list of numbers between say the result of (50-68) / (-68 + 50) and 50, then check if 0 is among if so update the count i.e.
if 0 in list_of_numbers:
count += 0
from aocd.models import Puzzle
p = Puzzle(year=2025, day=1)
inp = p.input_data
split_inp = inp.splitlines()
ex = (p.examples[0].input_data).splitlines()
print(ex)['L68', 'L30', 'R48', 'L5', 'R60', 'L55', 'L1', 'L99', 'R14', 'L82']
ex['L68', 'L30', 'R48', 'L5', 'R60', 'L55', 'L1', 'L99', 'R14', 'L82']Using range()
Lets try using range() to test out our idea above. We shall try using range() to see if we can go through our values from init_postion till the final raw position to see if a 0 exists in that range then incrementing our count by 1 for every time it does.
init_pos = 50
count = 0
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
print(count)984
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
print(init_pos)82
52
0
95
55
0
99
0
14
32
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
print(init_pos, (move*distance))82 -68
52 -30
0 48
95 -5
55 60
0 -55
99 -1
0 -99
14 14
32 -82
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
new_pos = ((move*distance)+init_pos)
init_pos = (new_pos%100)
print(new_pos, init_pos)-18 82
52 52
100 0
-5 95
155 55
0 0
-1 99
0 0
14 14
-68 32
ca = 0
if 0 in range(-18, 51):
c += 1
print(c)1
cb = 0
for n in range(-18,51):
if n == 0:
cb += 1
print(cb)1
Which is more efficient , the cell using ca or the one using cb
The cell using ca is more efficient:
ca = 0
if 0 in range(-18, 51):
ca += 1
range membership is checked mathematically, without generating or looping through every number. It runs in constant time, O(1).
The cb version checks each value one by one:
cb = 0
for n in range(-18, 51):
if n == 0:
cb += 1
That takes time proportional to the range size, O(n).
For this tiny range, the difference is negligible. But for Part Two, ca's logic is not enough: a rotation such as R1000 can pass through 0 ten times. You need to count complete 100-step cycles as well as whether the remaining part crosses zero.
$0.0277
prompt_tokens=90,641 | completion_tokens=272 | total_tokens=90,913 | reasoning_tokens=79 | cost=0.027681900000000002
So i know from the advent of code problem page that there are 3 moves that pass through 0 and as we saw in part 1 another 3 that end up at 0. So the above approach is wrong somewhere.
cb seems to be more efficient, lets adapt that logic into a solution for part 2
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
new_pos = ((move*distance)+init_pos)
if 0 in range(new_pos, init_pos):
count += 1
init_pos = (new_pos%100)
print(count)4
in part two would cb's logic be enough
The general idea behind cb can work, but the exact version you wrote is not enough for Part Two.
Your current code:
for n in range(-18, 51):
if n == 0:
cb += 1
only checks whether the unwrapped movement passes through exactly 0. Part Two needs to count every time the dial reaches a position equivalent to 0, including:
0100-100200- etc.
For example:
Start at 50
Move right 1000
The unwrapped positions include:
50, 51, 52, ..., 100, ..., 200, ..., 1000
The dial reaches zero at 100, 200, ..., 1000: ten times.
So the click-by-click idea would need to check:
if n % 100 == 0:
rather than:
if n == 0:
Conceptually:
start = 50
move = 68
step = -1
for n in range(start + step, start + step * move, step):
if n % 100 == 0:
count += 1
But this is awkward because the range must handle both left and right rotations correctly, and it loops once per click. A rotation of R1000000 would require a million iterations.
So:
- For correctness: simulating every click can work.
- For efficiency: it is better to count full 100-click cycles mathematically, then check the remaining partial movement.
- Your current
cbcode: not yet sufficient for Part Two.
$0.0259
prompt_tokens=90,945 | completion_tokens=543 | total_tokens=91,488 | cached_tokens=8,778 | reasoning_tokens=172 | cost=0.025890840000000002
reword the above to use the variables init_pos, move and the ones previously used, ie here for n in range(start + step, start + step * move, step):
Using your existing variables, where init_pos is the current position, move is -1 for left or 1 for right, and distance is the number of clicks:
for n in range(
init_pos + move,
init_pos + move * (distance + 1),
move
):
if n % 100 == 0:
count += 1
For example, starting at 50 with L68:
init_pos = 50
move = -1
distance = 68
for n in range(init_pos + move,
init_pos + move * (distance + 1),
move):
if n % 100 == 0:
count += 1
This produces the click positions from 49 through -18, including the endpoint. The + 1 is needed because Python's range excludes its stop value.
After counting the clicks, update the dial for the next rotation:
init_pos = (init_pos + move * distance) % 100
$0.0257
prompt_tokens=91,361 | completion_tokens=347 | total_tokens=91,708 | cached_tokens=8,778 | reasoning_tokens=107 | cost=0.025662840000000003
isnt doing (move * (distance + 1)) the same as doing ((distance*move)+move) which is more explanaible
Yes, they are mathematically equivalent because of the distributive property:
move * (distance + 1)
is the same as:
(move * distance) + move
For example, with move = -1 and distance = 68:
move * (distance + 1)
# -1 * 69 = -69
(move * distance) + move
# (-1 * 68) + (-1) = -69
The second version may be more explanatory because it shows:
move * distancegets the final position after the full movement+ moveextends the range by one step so that the endpoint is included
So this is perfectly valid:
for n in range(
init_pos + move,
(init_pos + move * distance) + move,
move
):
if n % 100 == 0:
count += 1
The equivalent compact form is:
for n in range(
init_pos + move,
init_pos + move * (distance + 1),
move
):
if n % 100 == 0:
count += 1
For learning, I agree that the expanded version can make the endpoint logic easier to see. The only issue is that the expression is slightly longer.
$0.0282
prompt_tokens=91,834 | completion_tokens=365 | total_tokens=92,199 | reasoning_tokens=64 | cost=0.0282072
now why do we do init+move for the 1st argument
init_pos + move gives the position after the first click.
The dial starts at init_pos, but the puzzle counts positions reached during the rotation, not the starting position before the rotation.
For example, with:
init_pos = 50
move = -1
distance = 68
the clicks are:
First click: 49
Then: 48
Then: 47
...
Final: -18
So the first argument is:
init_pos + move
which gives:
50 + (-1) # 49
That is why we use:
range(
init_pos + move,
(init_pos + move * distance) + move,
move
)
The three parts mean:
range(first_position, stopping_boundary, direction)
For L68, this becomes:
range(49, -19, -1)
Python excludes the stopping boundary -19, so the values include -18, the actual final position:
49, 48, 47, ..., -18
If we used init_pos as the first argument:
range(init_pos, ...)
the range would incorrectly include 50, even though the dial has not moved yet. That could also cause a false count if the dial started at 0; the initial position should not count as one of the rotation's clicks.
$0.0036
prompt_tokens=92,206 | completion_tokens=420 | total_tokens=92,626 | cached_tokens=91,791 | reasoning_tokens=93 | cost=0.00363423
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (((move*distance)+init_pos)%100)
if init_pos == 0:
count += 1
print(count)3
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(init_pos+move, ((distance*move)+move)):
if n%100 == 0:
count += 1
init_pos = (((move*distance)+init_pos)%100)
print(count)0
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(init_pos+move, (init_pos + (distance*move) + move), move):
if n%100 == 0:
count += 1
init_pos = (((move*distance)+init_pos)%100)
print(count)6
init_pos = 50
count = 0
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(init_pos+move, (init_pos + (distance*move) + move), move):
if n%100 == 0:
count += 1
init_pos = (((move*distance)+init_pos)%100)
print(count)5657
# LLM Orgarnized version
init_pos = 50
count = 0
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == "L":
move = -1
elif direction == "R":
move = 1
for n in range(
init_pos + move,
init_pos + move * (distance + 1),
move,
):
if n % 100 == 0:
count += 1
init_pos = (init_pos + move * distance) % 100
print(count)
6
def zeros_parse_a(dd_list: list[str]) -> int:
"""
zeros_parse_a takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one.
"""
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(init_pos+move, (init_pos + (distance*move) + move), move):
if n%100 == 0:
count += 1
init_pos = (((move*distance)+init_pos)%100)
return countzeros_parse_a(ex),zeros_parse_a(split_inp)(6, 5657)create for me a solution with this concept using range(start + step, start + step * move, step)
The conceptual change is to simulate each click, not just each rotation:
startis the dial’s current position before the rotation.stepis1for right and-1for left.distancetells us how many positions to visit.- The
rangestop value must be one step beyond the final click, because Python excludes the stop.
So the useful pattern is:
range(start + step, start + step * (distance + 1), step)
Here is the complete click-by-click solution:
def count_zero_clicks(rotations: list[str]) -> int:
pos = 50
count = 0
for rotation in rotations:
direction = rotation[0]
distance = int(rotation[1:])
step = 1 if direction == "R" else -1
for click_pos in range(
pos + step,
pos + step * (distance + 1),
step,
):
if click_pos % 100 == 0:
count += 1
pos = (pos + step * distance) % 100
return count
Test it with the example:
count_zero_clicks(ex)
This returns:
6
Why the range works for L68 from 50:
pos = 50
step = -1
distance = 68
range(49, -18, -1)
This visits the unwrapped positions:
49, 48, 47, ..., 1, 0, -1, ..., -18
The value 0 appears once, so the counter increases by one.
For R1000 from 50:
range(51, 1051, 1)
The values equivalent to zero are:
100, 200, 300, ..., 1000
So the counter increases ten times, as required.
The final position is updated after the inner loop:
pos = (pos + step * distance) % 100
That keeps pos in the dial’s displayed range 0 to 99, while click_pos deliberately remains unwrapped so that values such as 100, 200, or -100 can be detected.
$0.0289
prompt_tokens=91,498 | completion_tokens=789 | total_tokens=92,287 | reasoning_tokens=277 | cost=0.028869600000000002
put this outside of a function, and what is the dofference between it and
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(init_pos+move, ((distance*move)+move)):
if n%100 == 0:
count += 1
init_pos = (((move*distance)+init_pos)%100)
print(count)
Outside a function, it would look like this:
init_pos = 50
count = 0
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == "L":
move = -1
elif direction == "R":
move = 1
for n in range(
init_pos + move,
init_pos + move * (distance + 1),
move,
):
if n % 100 == 0:
count += 1
init_pos = (init_pos + move * distance) % 100
print(count)
For the example input, this gives:
6
The important difference from your version is the range expression.
Your version is:
range(init_pos + move, (distance * move) + move)
The corrected version is:
range(
init_pos + move,
init_pos + move * (distance + 1),
move,
)
There are three problems with the original version.
- The stop value does not include
init_pos.
Suppose the dial is at 50 and the instruction is L68.
The first click should be:
50 + (-1) # 49
The final unwrapped position is:
50 + (-1 * 68) # -18
So the range should go from 49 through -18:
range(49, -19, -1)
The corrected expression produces that:
range(
50 + (-1),
50 + (-1) * (68 + 1),
-1,
)
which is:
range(49, -19, -1)
Your expression produces:
range(49, -69)
It has used only the movement -68; it has not added the starting position 50 to the stopping point.
- You omitted the step argument.
Python's range has this form:
range(start, stop, step)
If you omit step, Python assumes:
step = 1
For a left rotation, move is -1, so the range must count downward:
range(49, -19, -1)
Without the -1, this is attempted:
range(49, -69)
Since the default step is positive but the stop is smaller than the start, it produces no values.
- The stop value must be one step beyond the final click.
Python excludes the stop value. For L68, the final click is -18, so the stop must be -19:
range(49, -19, -1)
That is why we write:
init_pos + move * (distance + 1)
The + 1 takes the stop one step beyond the actual final position.
The two updates have different jobs:
for n in range(...):
if n % 100 == 0:
count += 1
This checks every individual click for zero.
init_pos = (init_pos + move * distance) % 100
This calculates the final displayed dial position and stores it for the next rotation.
$0.0047
prompt_tokens=93,585 | completion_tokens=858 | total_tokens=94,443 | cached_tokens=92,163 | reasoning_tokens=113 | cost=0.0047358899999999995
use the variables init_pos, move and the ones previously used
Use init_pos for the current dial position and move for the direction:
move = -1forLmove = 1forR
The inner range() simulates each individual click. click_pos % 100 == 0 detects every visit to zero, including 100, 200, and -100.
init_pos = 50
count = 0
for i in split_inp:
direction = i[0]
distance = int(i[1:])
if direction == "L":
move = -1
elif direction == "R":
move = 1
for click_pos in range(
init_pos + move,
init_pos + move * (distance + 1),
move,
):
if click_pos % 100 == 0:
count += 1
init_pos = (init_pos + move * distance) % 100
print(count)
For the example list, use:
for i in ex:
instead of:
for i in split_inp:
The important distinction is:
click_pos
tracks every unwrapped click, while:
init_pos
is updated after the rotation and stores the dial’s final displayed position between 0 and 99.
$0.0037
prompt_tokens=92,077 | completion_tokens=424 | total_tokens=92,501 | cached_tokens=91,455 | reasoning_tokens=126 | cost=0.0036934499999999996
range(start + step, start + step * (distance + 1), step)def count_zero_clicks(rotations: list[str]) -> int:
pos = 50
count = 0
for rotation in rotations:
direction = rotation[0]
distance = int(rotation[1:])
step = 1 if direction == "R" else -1
for click_pos in range(
pos + step,
pos + step * (distance + 1),
step,
):
if click_pos % 100 == 0:
count += 1
pos = (pos + step * distance) % 100
return countcount_zero_clicks(ex)6count_zero_clicks(split_inp)5657Below i switch LLMs and ask the same question
in part two would cb's logic be enough
The basic idea behind cb can work, but your current version is not enough for Part Two.
Your current code checks one interval:
for n in range(-18, 51):
if n == 0:
cb += 1
That can detect that one rotation crosses 0, but it has two problems:
- A long rotation can cross
0several times. For example,R1000crosses it 10 times. - You must account for the current position and direction for every rotation.
A direct but slower Part Two solution would simulate every click:
pos = 50
count = 0
for rotation in ex:
direction = rotation[0]
distance = int(rotation[1:])
step = 1 if direction == 'R' else -1
for _ in range(distance):
pos = (pos + step) % 100
if pos == 0:
count += 1
Here, cb-style iteration is effectively being used: each click is checked individually. It correctly handles:
R1000 → 10 visits to 0
Its disadvantage is efficiency. If the total distance is very large, it performs one loop per click. A more efficient solution counts complete 100-step cycles mathematically, then checks the remaining partial rotation. But the click-by-click version is often the clearest first implementation for understanding Part Two.
$0.0036
prompt_tokens=90,898 | completion_tokens=415 | total_tokens=91,313 | cached_tokens=90,598 | reasoning_tokens=101 | cost=0.00355494
pos = 50
count = 0
for rotation in ex:
direction = rotation[0]
distance = int(rotation[1:])
step = 1 if direction == 'R' else -1
for _ in range(distance):
pos = (pos + step) % 100
if pos == 0:
count += 1now which solution is more efficient the one where i use for n in range(init_pos+move, (init_pos + (distance*move) + move), move): or the one where i use for _ in range(distance):`
Both solutions have the same time complexity:
O(distance)
They each process one iteration per click.
The first version:
for n in range(
init_pos + move,
init_pos + (distance * move) + move,
move,
):
if n % 100 == 0:
count += 1
tracks an unwrapped position such as -18, 100, or 200, then checks whether it is equivalent to zero.
The second version:
for _ in range(distance):
init_pos = (init_pos + move) % 100
if init_pos == 0:
count += 1
wraps the position after every click and checks the displayed position directly.
For learning and readability, I would choose the second:
for _ in range(distance):
The underscore means:
Repeat this loop
distancetimes; I do not need the loop counter itself.
It mirrors the problem statement: each repetition represents one click.
The first may be marginally faster in practice because range generates the integer sequence efficiently and you only update init_pos once per rotation. But the difference is unlikely to matter here, and the second is harder to get wrong.
Neither is efficient for extremely large distances, because both perform one iteration per click. A mathematical solution could count complete 100-click cycles directly, reducing each rotation to constant time, O(1).
$0.0274
prompt_tokens=95,956 | completion_tokens=565 | total_tokens=96,521 | cached_tokens=8,778 | reasoning_tokens=252 | cost=0.027433740000000005
i want the explanation with terms am familiar with as used in my zeros_count function, infact start by redefining the functions using the variable terms i used when creating my function zeros_count, use my examples as well for example the init_pos of 50, the moves made by ex list which contains ['L68', 'L30', 'R48', 'L5', 'R60', 'L55', 'L1', 'L99', 'R14', 'L82']
Let’s keep the same variable names as your zeros_count function:
dd_list: the list of rotationsinit_pos: the current dial position, starting at50count: how many times the dial reaches0i: one rotation, such as'L68'direction:'L'or'R'distance: the number of clicksmove:-1for left or1for right
Your Part 1 function counts only the final position after each rotation:
def zeros_count(dd_list: list[str]) -> int:
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
init_pos = (init_pos + move * distance) % 100
if init_pos == 0:
count += 1
return count
For the example list:
ex = ['L68', 'L30', 'R48', 'L5', 'R60',
'L55', 'L1', 'L99', 'R14', 'L82']
the final positions are:
Start at 50
L68 → 82
L30 → 52
R48 → 0 count = 1
L5 → 95
R60 → 55
L55 → 0 count = 2
L1 → 99
L99 → 0 count = 3
R14 → 14
L82 → 32
So Part 1 returns 3.
For Part 2, the important change is that distance may represent many individual clicks. Instead of updating init_pos once per rotation, update it once per click:
def zeros_count_part2(dd_list: list[str]) -> int:
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for _ in range(distance):
init_pos = (init_pos + move) % 100
if init_pos == 0:
count += 1
return count
The new inner loop is:
for _ in range(distance):
For i = 'L68':
direction = 'L'
distance = 68
move = -1
So this runs 68 times. The first few clicks are:
Starting init_pos: 50
1st click: init_pos = (50 + -1) % 100 = 49
2nd click: init_pos = (49 + -1) % 100 = 48
...
50th click: init_pos = 0
When init_pos becomes 0:
if init_pos == 0:
count += 1
So count increases even though the rotation eventually ends at 82.
For the whole example:
zeros_count_part2(ex)
the result is:
6
The six visits are:
L68: passes through0onceR48: ends at0R60: passes through0onceL55: ends at0L99: ends at0L82: passes through0once
The conceptual difference is:
# Part 1: move the whole distance at once
init_pos = (init_pos + move * distance) % 100
versus:
# Part 2: move one click at a time
for _ in range(distance):
init_pos = (init_pos + move) % 100
Part 1 sees only where the dial finishes. Part 2 sees every position the dial visits.
$0.0275
prompt_tokens=93,222 | completion_tokens=1,070 | total_tokens=94,292 | cached_tokens=8,778 | reasoning_tokens=159 | cost=0.02752254
what i wanted to know is why do (init_pos + move)%100 instead of the original calculation of init_pos = (((move*distance)+init_pos)%100)
The difference is how much movement happens in each loop iteration.
Your original calculation moves the dial through the entire rotation at once:
init_pos = (init_pos + move * distance) % 100
For the first item in ex:
i = 'L68'
move = -1
distance = 68
init_pos = 50
The calculation is:
init_pos = (50 + (-1 * 68)) % 100
= -18 % 100
= 82
It jumps directly from 50 to 82. It does not record the 68 positions visited along the way.
For Part 2, we need to inspect each individual click, so we use:
for _ in range(distance):
init_pos = (init_pos + move) % 100
Here, each loop represents exactly one click.
For L68, the first few iterations are:
Starting init_pos = 50
1st click: init_pos = (50 + -1) % 100 = 49
2nd click: init_pos = (49 + -1) % 100 = 48
3rd click: init_pos = (48 + -1) % 100 = 47
...
50th click: init_pos = 0
...
68th click: init_pos = 82
So:
moveis the size of one click:-1or1distancetells us how many times to repeat that one-click movement
That is why the inner calculation is:
init_pos = (init_pos + move) % 100
rather than:
init_pos = (init_pos + move * distance) % 100
If you used move * distance inside the loop, you would move 68 clicks 68 times:
for _ in range(distance):
init_pos = (init_pos + move * distance) % 100
That would mean:
move 68 clicks
move 68 clicks
move 68 clicks
...
which is far too much movement.
The two approaches produce the same final position when used correctly:
# Move the whole rotation at once
init_pos = (init_pos + move * distance) % 100
and:
# Move one click at a time
for _ in range(distance):
init_pos = (init_pos + move) % 100
But they provide different information:
- The first gives only the final position.
- The second lets you count every time the dial reaches
0.
For L68, both eventually finish at 82, but only the one-click version notices that the dial passed through 0 during the rotation.
$0.0044
prompt_tokens=94,224 | completion_tokens=696 | total_tokens=94,920 | cached_tokens=93,179 | reasoning_tokens=76 | cost=0.00436167
ok am starting to get it so instead of saying lets move in the correct direction by these number of steps in our case this would be the distance which gives us our final init_position, we say lets move 1 step in the correct direction for this number of step / distance, at every step checking if our new init_pos is 0
Exactly. You have the distinction:
- Part 1: move the dial by the whole
distancein one calculation, then check the finalinit_pos. - Part 2: repeat a one-click movement
distancetimes, checkinginit_posafter every click.
Using your variable names:
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for _ in range(distance):
init_pos = (init_pos + move) % 100
if init_pos == 0:
count += 1
For L68:
init_pos starts at 50
move is -1
distance is 68
The inner loop says:
Move one step left, 68 times. After every step, check whether the new
init_posis0.
The first steps are:
50 → 49
49 → 48
48 → 47
...
1 → 0
0 → 99
...
The dial reaches 0 during the rotation, then eventually finishes at 82.
One small wording refinement: distance is the number of clicks, while init_pos is the current position. So the algorithm is:
For each rotation, move one click in the correct direction, repeating for the rotation’s distance, and increase
countwhenever the new position is zero.
$0.0267
prompt_tokens=94,967 | completion_tokens=333 | total_tokens=95,300 | cached_tokens=8,778 | cost=0.026719439999999997
Alternate Approach
we can also check every step in distance, similar to what we are doing above
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(distance):
init_pos = (init_pos + move) % 100
#print(init_pos)init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(distance):
init_pos = (init_pos + move) % 100
if init_pos == 0:
count += 1
print(count)6
init_pos = 50
count = 0
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(distance):
init_pos = (init_pos + move) % 100
if init_pos == 0:
count += 1
print(count)5657
def zeros_parse_b(dd_list: list[str]) -> int:
"""
zeros_parse_a takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one.
"""
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
move = -1
elif direction == 'R':
move = 1
for n in range(distance):
init_pos = (init_pos + move) % 100
if init_pos == 0:
count += 1
return countzeros_parse_b(ex),zeros_parse_b(split_inp)(6, 5657)Going for efficiency
zero_parse_a and zero_parse_b goes through every step in distance, for each set of dial instructions and checks if any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one.
However going through each move made, position by position seems / sounds inefficient especially if done at scale. We should be able / want to make this process more efficient. Since we know the starting and ending points, We can try to come up with a way to check whether there is a 0 between the starting position and the ending position without going through all positions.
Lets think of our original approach, calculate the distance between the start and end point, and see how many times an interval of 0 / 100 appears. How else can we do this without range since that seems to go through every step, atleast in our approach.
Getting a positive number and dividing it by our highest bound, in this case 99, so we use 100, tells us how many times intervals of 100 exist in the number.
LLM Exploration
you previosuly noted that this method is inefficient given how it goes through every number, doing this for a large list seems inefficient , possibly slow, compute expensive etc, is there another approach i can use for this, i was previosuly insipired by the way you can do
if 0 in range():
do x
kind of thing
Yes. You can use the same interval idea as:
0 in range(...)
but Part 2 needs a count, not just a yes/no answer. It also needs to recognise that 0, 100, -100, and so on all represent dial position 0.
The efficient approach is:
Count how many multiples of
100lie in the unwrapped interval travelled by the dial.
There is no need to simulate every click.
For a right rotation, starting at init_pos and moving distance clicks, the unwrapped positions are:
init_pos + 1, init_pos + 2, ..., init_pos + distance
The number of times this interval reaches a multiple of 100 is:
(init_pos + distance) // 100
For example, starting at 50 and moving right 150 clicks:
(50 + 150) // 100
# 2
The dial reaches zero at raw positions 100 and 200.
For a left rotation, the unwrapped positions are:
init_pos - 1, init_pos - 2, ..., init_pos - distance
The count can be calculated using floor division:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
For L68 from 50:
(50 - 1) // 100 - (50 - 68 - 1) // 100
which is:
49 // 100 - (-19) // 100
= 0 - (-1)
= 1
So the rotation passes through zero once.
The two formulas can be placed into your existing variable structure:
if direction == 'R':
count += (init_pos + distance) // 100
init_pos = (init_pos + distance) % 100
elif direction == 'L':
count += ((init_pos - 1) // 100
- (init_pos - distance - 1) // 100)
init_pos = (init_pos - distance) % 100
The important detail is that init_pos is updated after counting the rotation. That way, the count uses the position where the rotation started.
This handles long movements efficiently:
# R1000 from position 50
(50 + 1000) // 100
# 10
It performs a fixed number of arithmetic operations regardless of whether distance is 10 or 10_000_000.
Your earlier idea:
0 in range(...)
is efficient because Python can test membership in an integer range mathematically. But it only answers whether there is at least one matching value. The formulas above extend that idea to count every crossed multiple of 100, including repeated full revolutions.
$0.0283
prompt_tokens=95,430 | completion_tokens=1,145 | total_tokens=96,575 | cached_tokens=8,778 | reasoning_tokens=516 | cost=0.028319940000000002
help me understand the elif, particulary the count step by step in the case of L
elif means “otherwise, if”. In this problem, each rotation is either R or L, so only one branch runs:
if direction == 'R':
# handle a right rotation
elif direction == 'L':
# handle a left rotation
For the left-rotation branch:
elif direction == 'L':
count += ((init_pos - 1) // 100
- (init_pos - distance - 1) // 100)
init_pos = (init_pos - distance) % 100
The two lines do different jobs:
- Count how many times this left rotation reaches zero.
- Update
init_posto the final position.
Take the first example rotation, L68.
Before the rotation:
init_pos = 50
distance = 68
A left rotation moves downward, so the raw positions visited are:
49, 48, 47, ..., 1, 0, -1, ..., -18
The dial is at zero whenever the raw position is a multiple of 100:
..., -200, -100, 0, 100, 200, ...
In this interval, only 0 occurs, so the answer for this rotation is 1.
The count expression is:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
Substitute the values:
(50 - 1) // 100 - (50 - 68 - 1) // 100
Simplify:
49 // 100 - (-19) // 100
Python's floor division gives:
0 - (-1)
Therefore:
1
So this line:
count += 1
adds one to the total count.
The -1 parts make the interval boundaries correct. The rotation visits positions from:
init_pos - 1
through:
init_pos - distance
For L68, that is:
49 through -18
The formula counts multiples of 100 in that interval by calculating:
number of multiples up to 49
minus
number of multiples before -18
That is why the lower boundary uses:
init_pos - distance - 1
For the next rotation, L30, the current position is 82:
init_pos = 82
distance = 30
The visited raw positions are:
81, 80, ..., 52
There are no multiples of 100 there. The formula gives:
(82 - 1) // 100 - (82 - 30 - 1) // 100
81 // 100 - 51 // 100
0 - 0
So this rotation adds:
0
Then the final position is updated separately:
init_pos = (82 - 30) % 100
= 52
The full left branch can therefore be read as:
elif direction == 'L':
# Count every zero-crossing during the left rotation
count += ((init_pos - 1) // 100
- (init_pos - distance - 1) // 100)
# Move the dial to its final position
init_pos = (init_pos - distance) % 100
For a long left rotation, the same calculation counts multiple complete revolutions. For example, L150 from 50 visits raw positions from 49 down to -100, reaching:
0 and -100
Both represent dial position zero, so the count is 2, without looping through all 150 clicks.
$0.0287
prompt_tokens=96,003 | completion_tokens=1,280 | total_tokens=97,283 | cached_tokens=8,778 | reasoning_tokens=419 | cost=0.028734839999999998
I still dont get it what the goal of this L count how did ypu come up with it
The goal of the L count is:
Count how many individual clicks during a left rotation land on dial position
0.
It is not counting the final position only. It is counting every time the dial reaches zero, including after a full revolution.
Start with the first example:
init_pos = 50
rotation = L68
distance = 68
A left rotation visits:
49, 48, 47, ..., 1, 0, 99, ..., 82
The first time it reaches 0 is after 50 clicks:
50 → 49 # 1 click
...
1 → 0 # 50 clicks
The remaining clicks go from 0 to 82, so there is no second visit to zero.
Therefore, L68 contributes:
1
The simplest way to calculate the count is:
if init_pos > 0:
first_zero = init_pos
else:
first_zero = 100
Why?
- From position
50, moving left takes50clicks to reach0. - From position
82, moving left takes82clicks to reach0. - From position
0, you must move a complete 100 clicks before reaching0again.
Then ask whether the rotation is long enough to reach that first zero:
if distance < first_zero:
zero_count = 0
else:
zero_count = 1 + (distance - first_zero) // 100
For L68 from 50:
first_zero = 50
distance = 68
Since 68 >= 50, it reaches zero once:
zero_count = 1 + (68 - 50) // 100
= 1 + 18 // 100
= 1
For L30 from the new position 52:
first_zero = 52
distance = 30
Since 30 < 52, it does not reach zero:
zero_count = 0
For L150 from 50:
First zero: after 50 clicks
Second zero: after 150 clicks
The formula gives:
zero_count = 1 + (150 - 50) // 100
= 1 + 100 // 100
= 2
Those two zero positions correspond to raw movement positions:
0 and -100
Both display as 0 on the circular dial.
So the left-rotation count can be understood as:
if init_pos > 0:
first_zero = init_pos
else:
first_zero = 100
if distance >= first_zero:
count += 1 + (distance - first_zero) // 100
Only after calculating this should you update the final position:
init_pos = (init_pos - distance) % 100
The earlier floor-division expression was just a compact mathematical version of this idea. It counts the same zero positions, but the first_zero version makes the reasoning much easier to see.
$0.0309
prompt_tokens=96,737 | completion_tokens=1,021 | total_tokens=97,758 | reasoning_tokens=319 | cost=0.0308589
.
The next step is to combine the L logic with the R logic. First, focus on the shared idea:
Find how many clicks it takes to reach
0for the first time. Any additional full groups of 100 clicks produce additional visits to0.
For a left rotation:
init_pos = 50
distance = 68
first_zero = init_pos # 50 clicks left reaches 0
Because 68 is enough to reach that first zero:
1 + (distance - first_zero) // 100
# 1 + (68 - 50) // 100
# 1
Then update the dial’s final position:
init_pos = (init_pos - distance) % 100
# 82
For the next example rotation, L30, the new starting position is 82, not 50:
first_zero = 82
distance = 30
Because 30 < 82, the dial does not reach zero:
0
The key sequence is therefore:
1. Use the current init_pos.
2. Calculate how many zero visits this rotation contains.
3. Add that number to count.
4. Update init_pos to the rotation's final position.
5. Repeat for the next rotation.
$0.0038
prompt_tokens=97,472 | completion_tokens=364 | total_tokens=97,836 | cached_tokens=96,694 | reasoning_tokens=70 | cost=0.00378942
give me the full code cell
The efficient version still follows your zeros_count structure. The difference is that it counts how many multiples of 100 the rotation crosses, rather than simulating each click.
def zeros_count_part2(dd_list: list[str]) -> int:
"""
Count every click that leaves the dial pointing at 0.
The dial starts at position 50.
"""
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'R':
# Count multiples of 100 reached while moving right.
count += (init_pos + distance) // 100
# Update the final dial position.
init_pos = (init_pos + distance) % 100
elif direction == 'L':
# Count multiples of 100 reached while moving left.
count += (
(init_pos - 1) // 100
- (init_pos - distance - 1) // 100
)
# Update the final dial position.
init_pos = (init_pos - distance) % 100
else:
raise ValueError(f"Invalid direction: {direction}")
return count
# Example input
ex = [
'L68', 'L30', 'R48', 'L5', 'R60',
'L55', 'L1', 'L99', 'R14', 'L82'
]
print(zeros_count_part2(ex)) # 6
print(zeros_count_part2(split_inp)) # Your Part 2 answer
The key difference from Part 1 is that count is updated before init_pos changes, because the counting formula needs the position where the rotation started.
$0.0280
prompt_tokens=95,965 | completion_tokens=902 | total_tokens=96,867 | cached_tokens=8,778 | reasoning_tokens=516 | cost=0.02804304
so are you saying we break down for example 49 to -18, we breakdown into 2 parts 49 - 0, then -1 to -18, calculate if any of these positions reaches zero then add them up, why not just do (init_pos + distance) // 100 like with R
You’re close, but we do not need to split the left movement into two separate calculations.
For L68 from init_pos = 50, the raw positions after each click are:
49, 48, 47, ..., 1, 0, -1, ..., -18
This is one interval:
-18 through 49
The dial points at zero whenever the raw position is a multiple of 100:
..., -200, -100, 0, 100, 200, ...
Within -18 through 49, only 0 appears, so the count is 1.
For a right movement, the raw positions go upward. For example, R60 from 50 visits:
51, 52, ..., 99, 100, ..., 110
The only multiple of 100 is 100, so:
(init_pos + distance) // 100
works:
(50 + 60) // 100
# 110 // 100
# 1
That formula works because the starting position is between 0 and 99, so there are no multiples of 100 before it. It simply counts how many multiples of 100 the endpoint has passed.
For a left movement, the endpoint can become negative:
init_pos - distance
For L68:
50 - 68
# -18
Now ordinary positive // 100 counting is not enough. We need to count the multiples of 100 between the start and end while moving downward.
The left formula does that:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
Substituting init_pos = 50 and distance = 68:
(50 - 1) // 100 - (50 - 68 - 1) // 100
49 // 100 - (-19) // 100
Python gives:
0 - (-1)
# 1
Why does (-19) // 100 equal -1? Because Python floor division rounds down:
-19 // 100
# -1
That difference, 0 - (-1), tells us that one multiple of 100 was crossed: 0.
If you used the right-rotation formula for L68:
(init_pos + distance) // 100
you would get:
(50 + 68) // 100
# 1
That happens to give the correct answer by coincidence. But for L30 from 82:
(82 + 30) // 100
# 1
This incorrectly says the dial reaches zero. In reality, the raw positions are only:
81, 80, ..., 52
No zero is crossed.
The correct left formula gives:
(82 - 1) // 100 - (82 - 30 - 1) // 100
81 // 100 - 51 // 100
# 0 - 0
# 0
So:
- For
R, positions move upward, and(init_pos + distance) // 100counts upward multiples of100. - For
L, positions move downward, so we count the multiples of100between the starting and ending boundaries using the subtraction formula.
Your idea of looking from 49 down to -18 is correct. The formula is simply a compact way to count whether that interval contains 0, -100, -200, and so on, without checking each individual position.
$0.0055
prompt_tokens=98,309 | completion_tokens=1,302 | total_tokens=99,611 | cached_tokens=97,429 | reasoning_tokens=460 | cost=0.005530470000000001
what are we trying to do here
count += ( (init_pos - 1) // 100 - (init_pos - distance - 1) // 100 ), lets start by breaking it down and seeing what we are doing at each step ie why are we calculating (init_pos - 1) // 100, what does it give us then why (init_pos - distance - 1) // 100 and what does the subtraction do
The whole expression calculates:
How many times does this left rotation land on a dial position equivalent to
0?
For the dial, positions equivalent to zero are raw numbers such as:
..., -200, -100, 0, 100, 200, ...
For a left rotation:
init_pos = 50
distance = 68
the dial visits raw positions:
49, 48, ..., 0, ..., -18
The starting position 50 is not included, because the problem counts positions reached after clicks. So the interval is:
init_pos - distance through init_pos - 1
-18 through 49
The formula is:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
Break it into two parts.
First:
(init_pos - 1) // 100
Why init_pos - 1?
Because the first position reached is one step to the left:
50 - 1 = 49
So this becomes:
49 // 100
# 0
Next:
(init_pos - distance - 1) // 100
First calculate the lowest raw position reached:
init_pos - distance
= 50 - 68
= -18
Because -18 should be included in the interval, we subtract one more:
-18 - 1 = -19
So this becomes:
-19 // 100
# -1
Now subtract the two results:
0 - (-1)
# 1
That tells us the rotation reaches one multiple of 100:
0
So we add one to count:
count += 1
The reason the subtraction works is that the two floor divisions mark the boundaries of the interval:
lowest position: -18
highest position: 49
The expression counts multiples of 100 in that interval:
-18 through 49
Only 0 is in that interval, so the result is 1.
For comparison, take the next left rotation, L30, after the first move:
init_pos = 82
distance = 30
The raw positions visited are:
81, 80, ..., 52
There is no zero in that range.
The formula gives:
(init_pos - 1) // 100
# (82 - 1) // 100
# 81 // 100
# 0
and:
(init_pos - distance - 1) // 100
# (82 - 30 - 1) // 100
# 51 // 100
# 0
Subtract:
0 - 0
# 0
So L30 adds nothing to count.
For a longer example, L150 from 50:
init_pos = 50
distance = 150
The raw positions visited are:
49 down to -100
This interval contains two zero-equivalent positions:
0 and -100
The formula gives:
(50 - 1) // 100
# 49 // 100
# 0
(50 - 150 - 1) // 100
# -101 // 100
# -2
Then:
0 - (-2)
# 2
So L150 contributes two visits to zero.
In short:
count += (
(init_pos - 1) // 100
- (init_pos - distance - 1) // 100
)
means:
- Find the highest raw position reached.
- Find just before the lowest raw position reached.
- Use floor division by
100to identify how many 100-step boundaries lie between them. - Subtract the boundary counts.
- Add the number of zero visits to
count.
It counts the zero visits during the rotation. It does not calculate the final init_pos; that remains a separate step:
init_pos = (init_pos - distance) % 100
$0.0056
prompt_tokens=98,343 | completion_tokens=1,313 | total_tokens=99,656 | cached_tokens=97,429 | reasoning_tokens=342 | cost=0.00556047
-19//100-1-19/100-0.19-200//100-2-100//100-1-260//100-3ok so here is my understanding now, if direction is R, right, we calculate how many times 0 appears every time it appears we add a 1 to the count by adding the distance and seeing how many times multiples of 100 appear, if the direction is negative meaning it moves downward , we can calculate how mnay multiples appear by subtracting the floor divison over 100 of the distance between the 1st position our dial takes and the floor division of last position over 100, how does my understanding sound
Your understanding is mostly right. One important refinement:
You are not calculating the floor division of the distance between the first and last positions. You are counting how many multiples of 100 lie in the interval of raw positions visited.
For a right rotation from init_pos, the raw positions are:
init_pos + 1, init_pos + 2, ..., init_pos + distance
So:
(init_pos + distance) // 100
counts how many multiples of 100 have been reached.
For example, R60 from 50 visits raw positions 51 through 110. The only multiple of 100 is 100:
(50 + 60) // 100
# 110 // 100
# 1
For a left rotation, the raw positions are:
init_pos - 1, init_pos - 2, ..., init_pos - distance
For L68 from 50, that is:
49 down to -18
The formula is:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
Substitute the values:
(50 - 1) // 100 - (50 - 68 - 1) // 100
49 // 100 - (-19) // 100
0 - (-1)
# 1
The subtraction compares the two boundaries:
49is the first position reached-19is one position below the last position reached,-18
The interval being counted is therefore:
-18 through 49
That interval contains one multiple of 100:
0
So we add 1 to count.
For a longer left movement, L150 from 50, the visited raw positions are:
49 down to -100
The zero-equivalent multiples are:
0 and -100
The formula gives:
(50 - 1) // 100 - (50 - 150 - 1) // 100
= 49 // 100 - (-101) // 100
= 0 - (-2)
= 2
So the refined summary is:
For
R, count the multiples of100reached while raw positions increase. ForL, count the multiples of100reached while raw positions decrease. The floor-division expressions count those multiples without checking every click individually.
Then, separately, update the final dial position:
init_pos = (init_pos + move * distance) % 100
The counting calculation tells you how many times zero was reached during the rotation; this update tells you where the dial ends.
$0.0316
prompt_tokens=100,654 | completion_tokens=798 | total_tokens=101,452 | reasoning_tokens=174 | cost=0.0316326
how can i add to my summary to encompass the different methods used to calculate the multiples in the intervals of the positions in our left case and the multiples in the total for our right case, why cant we directly calculate the multiples in the total for our left case like we did for our right case R
Your summary could say:
For each rotation, we imagine the dial moving through raw positions, before applying
% 100. The dial points at zero whenever a raw position is a multiple of100:..., -200, -100, 0, 100, 200, ....
- For
R, the raw positions increase frominit_pos + 1toinit_pos + distance. We count the multiples of100in that upward interval.- For
L, the raw positions decrease frominit_pos - 1toinit_pos - distance. We count the multiples of100in that downward interval.- The final position is then wrapped with
% 100.
For R, the interval is:
init_pos + 1 through init_pos + distance
The count is:
(init_pos + distance) // 100 - init_pos // 100
Because init_pos is always between 0 and 99, init_pos // 100 is always 0, so this simplifies to:
(init_pos + distance) // 100
For example, R60 from 50:
Raw positions: 51 through 110
Multiples of 100: 100
(50 + 60) // 100
# 110 // 100
# 1
For L, the interval is reversed in direction:
init_pos - distance through init_pos - 1
So we count the multiples of 100 between those two boundaries:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
For L68 from 50:
Raw positions: -18 through 49
Multiples of 100: 0
(50 - 1) // 100 - (50 - 68 - 1) // 100
= 49 // 100 - (-19) // 100
= 0 - (-1)
= 1
The reason we cannot simply use:
(init_pos + distance) // 100
for L is that this formula describes movement toward larger numbers. But a left rotation moves toward smaller numbers.
For example, L30 from 82 visits:
81, 80, ..., 52
It never reaches zero. But the right-style formula would give:
(82 + 30) // 100
# 112 // 100
# 1
That incorrectly counts a zero because it imagines movement from 82 upward to 112, as if the direction were right.
The matching formulas are therefore:
# Right: count multiples in an increasing interval
right_count = (init_pos + distance) // 100 - init_pos // 100
# Left: count multiples in a decreasing interval
left_count = (
(init_pos - 1) // 100
- (init_pos - distance - 1) // 100
)
The difference is not that left rotations use a completely different idea. Both methods count multiples of 100 in an interval. The formulas differ because:
Rtravels from a smaller raw number to a larger raw number.Ltravels from a larger raw number to a smaller raw number.
This is also why the -1 values matter: they make sure the starting position is excluded, while the first and last positions reached by actual clicks are included.
$0.0052
prompt_tokens=101,394 | completion_tokens=1,096 | total_tokens=102,490 | cached_tokens=100,611 | reasoning_tokens=309 | cost=0.0052260299999999996
so i wanted all the facts included in my summary inlcuding things like (init_pos + distance) // 100 - init_pos // 100 Because init_pos is always between 0 and 99, init_pos // 100 is always 0, so this simplifies to: (init_pos + distance) // 100
so lets go through this again R is (init_pos + 1) to (init_pos + distance) so say in the case of R68 starting from 50 would be ((50+1)-(50+68)) while L is the reverse of (init_pos - 1) to (init_pos-distance-1) so say in the case of L68 starting from 50 would be ((50-1)-(50-68)), I Then add //100 to make the subtraction between floor divided numbers giving me multpiples i can add to count ie R = ((50+1)//100-(50+68)//100) and L = ((50-1)//100 -(50-68)//100)
You have the main idea, but a few details need correcting.
The goal is to count the multiples of 100 in the raw positions visited during a rotation. Those multiples represent dial position 0:
..., -200, -100, 0, 100, 200, ...
The starting position is not counted unless a click moves the dial back to it after a full revolution.
For a right rotation, the dial moves through the increasing interval:
init_pos + 1, ..., init_pos + distance
Starting at 50, an R68 rotation visits:
51, 52, ..., 118
The multiples of 100 in that interval are:
100
To count them generally:
(init_pos + distance) // 100 - init_pos // 100
Substituting the values:
(50 + 68) // 100 - 50 // 100
= 118 // 100 - 50 // 100
= 1 - 0
= 1
The first term counts multiples of 100 up to the ending raw position. The second removes multiples at or below the starting boundary.
Because init_pos is always between 0 and 99:
init_pos // 100
is always 0. Therefore, the right formula simplifies to:
(init_pos + distance) // 100
For a left rotation, the dial moves through the decreasing interval:
init_pos - 1, ..., init_pos - distance
Starting at 50, an L68 rotation visits:
49, 48, ..., 0, ..., -18
The raw interval, written from smallest to largest, is:
-18 through 49
The only multiple of 100 in that interval is:
0
The correct formula is:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
Substituting the values:
(50 - 1) // 100 - (50 - 68 - 1) // 100
= 49 // 100 - (-19) // 100
= 0 - (-1)
= 1
The -1 on the second boundary is important. The last position visited is:
init_pos - distance
which is -18. We use one position below it, -19, so that -18 is included correctly in the interval count.
This matters when the final position itself is zero. For example, L50 from 50 visits:
49, 48, ..., 0
The formula gives:
(50 - 1) // 100 - (50 - 50 - 1) // 100
= 49 // 100 - (-1) // 100
= 0 - (-1)
= 1
If we omitted the final -1, we would get:
49 // 100 - 0 // 100
= 0
That would incorrectly miss the zero at the endpoint.
So your corrected summary could be:
For every rotation, I imagine the dial moving through raw positions before applying
% 100. Every raw multiple of100represents the dial pointing at0.For
R, the visited positions increase frominit_pos + 1toinit_pos + distance. The general count is:(init_pos + distance) // 100 - init_pos // 100Since
init_posis always between0and99,init_pos // 100is always0, so this simplifies to:(init_pos + distance) // 100For
L, the visited positions decrease frominit_pos - 1toinit_pos - distance. Counting the multiples of100in that interval gives:(init_pos - 1) // 100 - (init_pos - distance - 1) // 100The subtraction works because floor division tells us how many multiples of
100lie below each boundary. The-1adjustments exclude the starting position and include the final position reached by a click.After counting the zero visits, I update the final dial position separately:
init_pos = (init_pos + move * distance) % 100
One correction to your notation: this is not:
((50 + 1) - (50 + 68))
That subtraction would describe a difference between two positions. The interval is:
51 through 118
and the count is the difference between the floor divisions of its boundaries:
(50 + 68) // 100 - 50 // 100
Similarly, for L68, the interval is:
-18 through 49
and the count is:
(50 - 1) // 100 - (50 - 68 - 1) // 100
$0.0060
prompt_tokens=102,446 | completion_tokens=1,439 | total_tokens=103,885 | cached_tokens=101,351 | reasoning_tokens=283 | cost=0.00595923
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'R':
count += ((init_pos+distance)//100 - (init_pos+1)//100)
init_pos = (init_pos + distance)%100
elif direction == 'L':
count += ((init_pos - 1)//100 - (init_pos-distance-1)//100)
init_pos = (init_pos - distance)%100
print(count)6
init_pos = 50
count = 0
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'R':
count += (init_pos+distance)//100
init_pos = (init_pos + distance)%100
elif direction == 'L':
count += ((init_pos - 1)//100 - (init_pos-distance-1)//100)
init_pos = (init_pos - distance)%100
print(count)5657
ok so wouldnt (init_pos + distance) // 100 - init_pos // 100 be the same as (init_pos + distance) // 100 - init_pos + // 100
I think you mean:
(init_pos + distance) // 100 - init_pos // 100
versus:
(init_pos + distance) // 100 - (init_pos + 100) // 100
Those are not the same.
For the right-rotation formula, the correct version is:
(init_pos + distance) // 100 - init_pos // 100
Python interprets this as:
((init_pos + distance) // 100) - (init_pos // 100)
Because // has higher precedence than -.
Since init_pos is always between 0 and 99:
init_pos // 100
is always:
0
So the formula simplifies to:
(init_pos + distance) // 100
For example, with init_pos = 50 and distance = 60:
(50 + 60) // 100 - 50 // 100
110 // 100 - 0
1
That counts the one multiple of 100 reached: raw position 100.
But this:
(init_pos + distance) // 100 - (init_pos + 100) // 100
would give:
110 // 100 - 150 // 100
1 - 1
# 0
which is wrong, because the movement does reach 100.
Also, this expression:
(init_pos + distance) // 100 - init_pos + // 100
is invalid Python syntax because // must have a value on both sides.
The safest way to write the intended expression is with explicit parentheses:
right_count = (
(init_pos + distance) // 100
- (init_pos // 100)
)
And because init_pos is always in the range 0 to 99, this can be shortened to:
right_count = (init_pos + distance) // 100
$0.0043
prompt_tokens=102,276 | completion_tokens=555 | total_tokens=102,831 | cached_tokens=101,351 | reasoning_tokens=84 | cost=0.00431703
ok now give me a full well explained version / summary of what is happening here
Here is the complete picture using your variable names.
What the variables mean
init_pos
The dial’s current displayed position. It is always kept between 0 and 99.
distance
How many clicks the current rotation makes.
move
The direction:
move = 1 # R, right
move = -1 # L, left
count
How many individual clicks have landed on dial position 0.
The important distinction is:
init_posstores the wrapped dial position.- During counting, we imagine raw positions such as
100,-18, or-100. - Any raw multiple of
100represents the dial pointing at0.
For example:
0, 100, 200, -100, -200
all correspond to dial position 0.
Part 1: count only final positions
Your Part 1 logic moves the whole rotation at once:
init_pos = (init_pos + move * distance) % 100
For example, with L68 from 50:
init_pos = (50 + (-1 * 68)) % 100
= -18 % 100
= 82
This tells us the final position is 82, but it does not tell us that the dial passed through 0 during the rotation.
That is enough for Part 1, because Part 1 only asks whether the dial is at 0 after a complete rotation.
Part 2: count every click that reaches zero
Part 2 asks us to count every click that lands on 0, including zero reached during the middle of a rotation.
Instead of simulating every click, we count the multiples of 100 in the raw interval travelled.
Right rotations
For a right rotation, the raw positions increase:
init_pos + 1, init_pos + 2, ..., init_pos + distance
For example, R60 from 50 visits:
51, 52, ..., 100, ..., 110
The interval contains one multiple of 100:
100
The general counting formula is:
(init_pos + distance) // 100 - init_pos // 100
The first part:
(init_pos + distance) // 100
counts the multiples of 100 up to the ending raw position.
The second part:
init_pos // 100
removes the multiples that were already at or below the starting boundary.
Because init_pos is always between 0 and 99:
init_pos // 100
is always 0.
Therefore, the formula simplifies to:
(init_pos + distance) // 100
For R60 from 50:
(50 + 60) // 100 - 50 // 100
= 110 // 100 - 0
= 1
So we add one to count.
The right branch can be written as:
if direction == 'R':
count += (init_pos + distance) // 100
init_pos = (init_pos + distance) % 100
The final position is updated separately:
init_pos = (init_pos + distance) % 100
Left rotations
For a left rotation, the raw positions decrease:
init_pos - 1, init_pos - 2, ..., init_pos - distance
For example, L68 from 50 visits:
49, 48, ..., 1, 0, ..., -18
Written from smallest to largest, the interval is:
-18 through 49
The only multiple of 100 in that interval is:
0
The formula is:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
First part
(init_pos - 1) // 100
init_pos - 1 is the first position reached after the first click.
For L68 from 50:
init_pos - 1
= 50 - 1
= 49
Then:
49 // 100
# 0
Second part
(init_pos - distance - 1) // 100
The final raw position reached is:
init_pos - distance
For L68 from 50:
50 - 68
# -18
Because floor-division interval formulas need a boundary just below the final included position, we subtract one more:
-18 - 1
# -19
Then:
-19 // 100
# -1
Subtraction
Now subtract the two results:
49 // 100 - (-19) // 100
= 0 - (-1)
= 1
That tells us the interval contains one multiple of 100, namely 0.
So the left branch is:
elif direction == 'L':
count += (
(init_pos - 1) // 100
- (init_pos - distance - 1) // 100
)
init_pos = (init_pos - distance) % 100
Why the left formula is different from the right formula
The right formula counts multiples while numbers are increasing:
51, 52, ..., 110
The left formula counts multiples while numbers are decreasing:
49, 48, ..., -18
You cannot use the right formula for a left rotation because it would pretend the dial moved upward.
For example, L30 from 82 visits:
81, 80, ..., 52
It never reaches zero.
The right-style formula would incorrectly say:
(82 + 30) // 100
= 112 // 100
= 1
That is wrong because 82 + 30 describes moving right, not left.
The correct left formula gives:
(82 - 1) // 100 - (82 - 30 - 1) // 100
= 81 // 100 - 51 // 100
= 0 - 0
= 0
So L30 adds nothing to count.
Why the -1 values matter for left
Suppose the dial is at 50 and the instruction is L50.
The dial visits:
49, 48, ..., 1, 0
The final position 0 must be counted.
Using the formula:
(50 - 1) // 100 - (50 - 50 - 1) // 100
= 49 // 100 - (-1) // 100
= 0 - (-1)
= 1
The -1 makes sure the endpoint 0 is included.
Without it:
(50 - 1) // 100 - (50 - 50) // 100
= 49 // 100 - 0 // 100
= 0
That would incorrectly miss the zero at the end.
Complete efficient solution
init_pos = 50
count = 0
for i in split_inp:
direction = i[0]
distance = int(i[1:])
if direction == 'R':
# Count multiples of 100 while moving right.
count += (init_pos + distance) // 100
# Store the final displayed dial position.
init_pos = (init_pos + distance) % 100
elif direction == 'L':
# Count multiples of 100 while moving left.
count += (
(init_pos - 1) // 100
- (init_pos - distance - 1) // 100
)
# Store the final displayed dial position.
init_pos = (init_pos - distance) % 100
print(count)
For the example:
ex = [
'L68', 'L30', 'R48', 'L5', 'R60',
'L55', 'L1', 'L99', 'R14', 'L82'
]
the result is:
6
For your actual input, this method gives:
5657
One correction to your earlier version: the general right-rotation formula is:
(init_pos + distance) // 100 - init_pos // 100
not:
(init_pos + distance) // 100 - (init_pos + 1) // 100
The simplified version is valid because init_pos is always between 0 and 99:
(init_pos + distance) // 100
The final position update remains:
init_pos = (init_pos + move * distance) % 100
The count and the position update are separate:
Count raw multiples of 100 during the rotation.
Then calculate and store the wrapped final position.
$0.0372
prompt_tokens=109,444 | completion_tokens=2,425 | total_tokens=111,869 | reasoning_tokens=379 | cost=0.0371982
where does last//100 - (first-1)//100 come from
The formula
last // 100 - (first - 1) // 100
comes from counting the multiples of 100 in the inclusive interval:
first, first + 1, ..., last
For the dial, those multiples represent positions where the dial points at 0:
..., -200, -100, 0, 100, 200, ...
The idea is:
- Count the multiples of
100up to and includinglast. - Subtract the multiples of
100beforefirst. - What remains are the multiples inside
firstthroughlast.
The expression for step 2 is:
(first - 1) // 100
We use first - 1 because first itself should be included.
For example, the interval from -18 to 49 contains:
-18, ..., 0, ..., 49
There is one multiple of 100: 0.
Apply the formula:
last = 49
first = -18
last // 100 - (first - 1) // 100
Substitute:
49 // 100 - (-19) // 100
Python gives:
0 - (-1)
# 1
So there is one multiple of 100 in the interval.
For an interval from 51 to 110:
last = 110
first = 51
The interval contains only 100:
110 // 100 - (51 - 1) // 100
= 110 // 100 - 50 // 100
= 1 - 0
= 1
For an interval from -100 to 49, it contains:
-100 and 0
The formula gives:
49 // 100 - (-100 - 1) // 100
= 49 // 100 - (-101) // 100
= 0 - (-2)
= 2
So the formula counts both -100 and 0.
For a left rotation, the dial travels downward, but we can write its visited positions in increasing order. For L68 from 50:
Visited positions: 49 down to -18
Written as an interval:
first = -18
last = 49
Then:
last // 100 - (first - 1) // 100
becomes:
49 // 100 - (-19) // 100
# 1
Your left-rotation expression:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
is exactly the same formula with these substitutions:
last = init_pos - 1
first = init_pos - distance
So:
last // 100 - (first - 1) // 100
becomes:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
The important idea is that last // 100 and (first - 1) // 100 are boundary counts. Subtracting them leaves only the multiples of 100 inside the interval.
$0.0349
prompt_tokens=111,071 | completion_tokens=868 | total_tokens=111,939 | reasoning_tokens=115 | cost=0.034883700000000004
what i mean is shouldnt it be first from last , and isnt first - 1 only for the left, am thinking for right it would be first + 1
The key is to distinguish starting position from first position visited after a click.
For an interval of integer positions from first through last, the general formula is:
last // 100 - (first - 1) // 100
It always uses first - 1, regardless of whether the dial moved left or right. That is because we want to count multiples of 100 starting at first, so we subtract the count strictly before first.
For a right rotation from 50 by 68:
Starting position: 50
First visited: 51
Last visited: 118
So:
first = 51
last = 118
The formula is:
last // 100 - (first - 1) // 100
Substitute:
118 // 100 - (51 - 1) // 100
= 1 - 50 // 100
= 1 - 0
= 1
This counts the multiple 100.
Because the first visited position is init_pos + 1, we have:
first - 1
= (init_pos + 1) - 1
= init_pos
So the right formula becomes:
(init_pos + distance) // 100 - init_pos // 100
Since init_pos is between 0 and 99:
init_pos // 100 == 0
Therefore it simplifies to:
(init_pos + distance) // 100
For a left rotation from 50 by 68:
Starting position: 50
First visited while moving: 49
Last visited while moving: -18
But for the interval formula, we write the positions in increasing numerical order:
-18 through 49
Therefore:
first = -18
last = 49
The same general formula gives:
last // 100 - (first - 1) // 100
49 // 100 - (-18 - 1) // 100
= 0 - (-19 // 100)
= 0 - (-1)
= 1
So the left-specific expression:
(init_pos - 1) // 100 - (init_pos - distance - 1) // 100
is just the same interval formula after substituting:
last = init_pos - 1
first = init_pos - distance
You were thinking of using first + 1 for the right case. That would be wrong if first means the first visited position. The boundary before the first visited position is always:
first - 1
For example, R1 from 98 visits only:
99
The correct count is:
99 // 100 - (99 - 1) // 100
= 0 - 98 // 100
= 0
If we incorrectly used first + 1:
99 // 100 - (99 + 1) // 100
= 0 - 1
= -1
A negative count is impossible, so first + 1 cannot be the right boundary.
The cleanest summary is:
Count multiples of
100in an inclusive interval by taking the count up tolastand subtracting the count beforefirst:last // 100 - (first - 1) // 100For right movement,
first = init_pos + 1andlast = init_pos + distance.For left movement, reorder the downward path numerically:
first = init_pos - distanceandlast = init_pos - 1.The
first - 1adjustment is used in both cases because it excludes everything before the first position being counted.
$0.0061
prompt_tokens=111,913 | completion_tokens=1,366 | total_tokens=113,279 | cached_tokens=111,028 | reasoning_tokens=478 | cost=0.0060551400000000005
i still dont get it , explain to me in simpler terms or with an anlogy
Imagine a road with house numbers:
..., -100, 0, 100, 200, ...
These are the places where the dial shows 0.
Suppose you want to count how many special houses are between house first and house last, including both ends.
A useful trick is:
number_up_to_last - number_before_first
For multiples of 100, those two quantities are:
last // 100
(first - 1) // 100
So the formula is:
last // 100 - (first - 1) // 100
Why first - 1?
Because we want to exclude everything before first, but include first itself.
For example, count multiples of 100 from 51 through 118:
51, 52, ..., 100, ..., 118
There is one special number: 100.
Calculate:
118 // 100
# 1
This says there is one multiple of 100 up to 118.
Now calculate how many there are before 51:
(51 - 1) // 100
= 50 // 100
= 0
Subtract:
1 - 0
# 1
So the interval contains one multiple of 100.
The first - 1 is not specifically for left rotations. It is part of the general counting trick:
count through the end
-
count before the beginning
For a right rotation from 50 by 68:
First visited position: 51
Last visited position: 118
So:
first = 51
last = 118
The general formula is:
last // 100 - (first - 1) // 100
which becomes:
118 // 100 - (51 - 1) // 100
= 1 - 0
= 1
Since:
first - 1
= (init_pos + 1) - 1
= init_pos
the right formula becomes:
(init_pos + distance) // 100 - init_pos // 100
and because init_pos is between 0 and 99:
init_pos // 100
# 0
it simplifies to:
(init_pos + distance) // 100
For a left rotation from 50 by 68, the dial visits:
49, 48, ..., 0, ..., -18
Although it travels downward, write the same visited positions from smallest to largest:
-18 through 49
So:
first = -18
last = 49
Apply the same formula:
49 // 100 - (-18 - 1) // 100
0 - (-19 // 100)
0 - (-1)
# 1
Again, the answer is 1, because the interval contains one special number: 0.
So the simplest rule is:
last // 100 - (first - 1) // 100
means:
Count all special positions up to
last, then remove all special positions beforefirst.
For right movement:
first = init_pos + 1
last = init_pos + distance
For left movement, reverse the numerical order:
first = init_pos - distance
last = init_pos - 1
The direction changes which values are first and last. It does not change the general rule or replace first - 1 with first + 1.
$0.0053
prompt_tokens=112,873 | completion_tokens=895 | total_tokens=113,768 | cached_tokens=111,870 | reasoning_tokens=53 | cost=0.005268
Working Backwards
68//1000118//1001-18//100-1(-18//100) + 10(-118//100) + 1-1since the negative gives us a different answer. Lets try something else, lets try doing (last step - first step)//100.
Lets try out a use case starting from our initial position 50 to take our first step to our last step for L68 and R68. We dont start from initial position but from the first step taken which acts as one of our bounds.
when calculating the distance between the a and b using b - a, we always want to include the number a in the integer count so we go from b to the number before a which is a -1 , so in our right direction case we have to do from r_last to r_first-1
# R68
r_first = 50 + 1
r_last = 50 + 68
(r_last - (r_first-1))
(r_last - (r_first-1)) // 1000# L68
l_last = 50 -1
l_first = 50 - 68
(l_last - (l_first-1)) // 1000seems like the last - first-1 // 100 doesnt work , so lets try doing the floor division on each item separetly, so we just - the results
(r_last//100 - (r_first-1)//100) 1#actual interval count = 1
l_last = 50 -1
l_first = 50 - 68
((l_last)//100 - ((l_first)-1)//100)
#((50-1)//100 - ((50 - 68)-1)//100)1so in our case say R68, the first position is (init_pos+1), and our last step is (init_pos+distance), while for our left the first position is (init_pos -1 ) while the last step is (init_pos-distance).
we do our distance count from the numeric upper number to the lower one, so in our right number case we would subtract the first step from last position and step and in my left case that would be the vice versa.
So in our right case where r_first = init_pos + 1 and r_last = init_pos + distance, (r_last//100 - ((init_pos + 1)-1)//100) becomes (init_pos + distance//100 - (r_first-1)//100) while in our left case where l_last = init_pos - 1 and l_first = init_pos - distance, (l_last//100 - (l_first-1)//100) becomes (init_pos - 1//100 - ((init_pos - distance)-1)//100)
((init_pos + distance)//100 - ((init_pos + 1)-1)//100)
((init_pos - 1)//100 - ((init_pos - distance)-1)//100)so lets integrate this
init_pos = 50
count = 0
#for i in split_inp:
for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
count += ((init_pos - 1)//100 - ((init_pos - distance)-1)//100)
init_pos = (init_pos - distance) % 100
elif direction == 'R':
count += ((init_pos + distance)//100 - ((init_pos + 1)-1)//100)
init_pos = (init_pos + distance) % 100
print(count)6
init_pos = 50
count = 0
for i in split_inp:
#for i in ex:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
count += ((init_pos - 1)//100 - ((init_pos - distance)-1)//100)
init_pos = (init_pos - distance) % 100
elif direction == 'R':
count += ((init_pos + distance)//100 - ((init_pos + 1)-1)//100)
init_pos = (init_pos + distance) % 100
print(count)5657
def zeros_parse_eff(dd_list: list[str]) -> int:
"""
zeros_count takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one.
"""
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
count += ((init_pos - 1)//100 - ((init_pos - distance)-1)//100)
init_pos = (init_pos - distance) % 100
elif direction == 'R':
count += ((init_pos + distance)//100 - ((init_pos + 1)-1)//100)
init_pos = (init_pos + distance) % 100
return countzeros_parse_eff??def zeros_parse_eff(dd_list: list[str]) -> int:
"""
zeros_count takes a list of a sequence of rotations which start
with an L or R which indicates whether the rotation should be to
the left (toward lower numbers) or to the right (toward higher numbers)
followed by the rotation which has a distance value which indicates
how many clicks the dial should be rotated in that direction.
Args:
dd_list (list): A list of the input with the direction and distance value created using splitlines
Returns:
count (int): The number of times any click causes the dial to point at 0, regardless of whether it happens during a rotation or at the end of one.
"""
init_pos = 50
count = 0
for i in dd_list:
direction = i[0]
distance = int(i[1:])
if direction == 'L':
count += ((init_pos - 1)//100 - ((init_pos - distance)-1)//100)
init_pos = (init_pos - distance) % 100
elif direction == 'R':
count += ((init_pos + distance)//100 - ((init_pos + 1)-1)//100)
init_pos = (init_pos + distance) % 100
return count
File: /tmp/ipymini_76/233200314.py; line: 1
zeros_parse_eff(ex), zeros_parse_eff(split_inp)(6, 5657)%%timeit
zeros_parse_eff(ex)2.45 us +- 17.7 ns per loop (mean +- std. dev. of 7 runs, 100,000 loops each)
%%timeit
zeros_parse_a(ex)15.4 us +- 31.3 ns per loop (mean +- std. dev. of 7 runs, 100,000 loops each)
%%timeit
zeros_parse_b(ex)17.2 us +- 296 ns per loop (mean +- std. dev. of 7 runs, 100,000 loops each)
%%timeit
zeros_parse_eff(split_inp)1.11 ms +- 3.6 us per loop (mean +- std. dev. of 7 runs, 1,000 loops each)
%%timeit
zeros_parse_a(split_inp)18.8 ms +- 42.5 us per loop (mean +- std. dev. of 7 runs, 100 loops each)
%%timeit
zeros_parse_b(split_inp)20.8 ms +- 73.1 us per loop (mean +- std. dev. of 7 runs, 10 loops each)
import pandas as pd
results = [
{
"function": "zeros_parse_eff",
"example_result": zeros_parse_eff(ex),
"actual_result": zeros_parse_eff(split_inp),
"example_time": "2.45 µs",
"actual_time": "1.11 ms",
},
{
"function": "zeros_parse_a",
"example_result": zeros_parse_a(ex),
"actual_result": zeros_parse_a(split_inp),
"example_time": "15.4 µs",
"actual_time": "18.8 ms",
},
{
"function": "zeros_parse_b",
"example_result": zeros_parse_b(ex),
"actual_result": zeros_parse_b(split_inp),
"example_time": "17.2 µs",
"actual_time": "20.8 ms",
},
]
results_df = pd.DataFrame(results)
results_df| function | example_result | actual_result | example_time | actual_time | |
|---|---|---|---|---|---|
| 0 | zeros_parse_eff | 6 | 5657 | 2.45 µs | 1.11 ms |
| 1 | zeros_parse_a | 6 | 5657 | 15.4 µs | 18.8 ms |
| 2 | zeros_parse_b | 6 | 5657 | 17.2 µs | 20.8 ms |
So what i learn from part 2 is that there is many approaches to solve a prolem , some more efficient than others