Home
About
Blog
Products
Forum
Support
Contact
Sunbelt Computer Software
PL/B Language Development and Support
Home
About
Blog
Products
Forum
Support
Contact
algorithms-python/project_euler/problem_686/sol1.py at master · zinating/algorithms-python · GitHub
Skip to content
Navigation Menu
Sign in
Appearance settings
Platform
AI CODE CREATION
GitHub Copilot
Write better code with AI
GitHub Copilot app
Direct agents from issue to merge
MCP Registry
Integrate external tools
DEVELOPER WORKFLOWS
Actions
Automate any workflow
Codespaces
Instant dev environments
Issues
Plan and track work
Code Review
Manage code changes
Code Quality
Enforce quality at merge
APPLICATION SECURITY
GitHub Advanced Security
Find and fix vulnerabilities
Code security
Secure your code as you build
Secret protection
Stop leaks before they start
EXPLORE
Why GitHub
Documentation
Blog
Changelog
Marketplace
View all features
Solutions
BY COMPANY SIZE
Enterprises
Small and medium teams
Startups
Nonprofits
BY USE CASE
App Modernization
DevSecOps
DevOps
CI/CD
View all use cases
BY INDUSTRY
Healthcare
Financial services
Manufacturing
Government
View all industries
View all solutions
Resources
EXPLORE BY TOPIC
AI
Software Development
DevOps
Security
View all topics
EXPLORE BY TYPE
Customer stories
Events & webinars
Ebooks & reports
Business insights
GitHub Skills
SUPPORT & SERVICES
Documentation
Customer support
Community forum
Trust center
Partners
View all resources
Open Source
COMMUNITY
GitHub Sponsors
Fund open source developers
PROGRAMS
Security Lab
Maintainer Community
GitHub Stars
Archive Program
REPOSITORIES
Topics
Trending
Collections
Enterprise
ENTERPRISE SOLUTIONS
Enterprise platform
AI-powered developer platform
AVAILABLE ADD-ONS
GitHub Advanced Security
Enterprise-grade security features
Copilot for Business
Enterprise-grade AI features
Premium Support
Enterprise-grade 24/7 support
Pricing
Search
/
Sign in
Sign up
Appearance settings
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
zinating
/
algorithms-python
Public
forked from
TheAlgorithms/Python
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Files
Expand file tree
master
Breadcrumbs
algorithms-python
/
project_euler
/
problem_686
/
sol1.py
Copy path
Blame
More file actions
Blame
More file actions
Latest commit
History
History
History
160 lines (115 loc) · 5.11 KB
master
Breadcrumbs
algorithms-python
/
project_euler
/
problem_686
/
sol1.py
Copy path
Top
File metadata and controls
Code
Blame
160 lines (115 loc) · 5.11 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
Project Euler Problem 686: https://projecteuler.net/problem=686
2^7 = 128 is the first power of two whose leading digits are "12".
The next power of two whose leading digits are "12" is 2^80.
Define p(L,n) to be the nth-smallest value of j such that
the base 10 representation of 2^j begins with the digits of L.
So p(12, 1) = 7 and p(12, 2) = 80.
You are given that p(123, 45) = 12710.
Find p(123, 678910).
"""
import
math
def
log_difference
(
number
:
int
)
->
float
:
"""
This function returns the decimal value of a number multiplied with log(2)
Since the problem is on powers of two, finding the powers of two with
large exponents is time consuming. Hence we use log to reduce compute time.
We can find out that the first power of 2 with starting digits 123 is 90.
Computing 2^90 is time consuming.
Hence we find log(2^90) = 90*log(2) = 27.092699609758302
But we require only the decimal part to determine whether the power starts with 123.
So we just return the decimal part of the log product.
Therefore we return 0.092699609758302
>>> log_difference(90)
0.092699609758302
>>> log_difference(379)
0.090368356648852
"""
log_number
=
math
.
log
(
2
,
10
)
*
number
difference
=
round
((
log_number
-
int
(
log_number
)),
15
)
return
difference
def
solution
(
number
:
int
=
678910
)
->
int
:
"""
This function calculates the power of two which is nth (n = number)
smallest value of power of 2
such that the starting digits of the 2^power is 123.
For example the powers of 2 for which starting digits is 123 are:
90, 379, 575, 864, 1060, 1545, 1741, 2030, 2226, 2515 and so on.
90 is the first power of 2 whose starting digits are 123,
379 is second power of 2 whose starting digits are 123,
and so on.
So if number = 10, then solution returns 2515 as we observe from above series.
We will define a lowerbound and upperbound.
lowerbound = log(1.23), upperbound = log(1.24)
because we need to find the powers that yield 123 as starting digits.
log(1.23) = 0.08990511143939792, log(1,24) = 0.09342168516223506.
We use 1.23 and not 12.3 or 123, because log(1.23) yields only decimal value
which is less than 1.
log(12.3) will be same decimal value but 1 added to it
which is log(12.3) = 1.093421685162235.
We observe that decimal value remains same no matter 1.23 or 12.3
Since we use the function log_difference(),
which returns the value that is only decimal part, using 1.23 is logical.
If we see, 90*log(2) = 27.092699609758302,
decimal part = 0.092699609758302, which is inside the range of lowerbound
and upperbound.
If we compute the difference between all the powers which lead to 123
starting digits is as follows:
379 - 90 = 289
575 - 379 = 196
864 - 575 = 289
1060 - 864 = 196
We see a pattern here. The difference is either 196 or 289 = 196 + 93.
Hence to optimize the algorithm we will increment by 196 or 93 depending upon the
log_difference() value.
Let's take for example 90.
Since 90 is the first power leading to staring digits as 123,
we will increment iterator by 196.
Because the difference between any two powers leading to 123
as staring digits is greater than or equal to 196.
After incrementing by 196 we get 286.
log_difference(286) = 0.09457875989861 which is greater than upperbound.
The next power is 379, and we need to add 93 to get there.
The iterator will now become 379,
which is the next power leading to 123 as starting digits.
Let's take 1060. We increment by 196, we get 1256.
log_difference(1256) = 0.09367455396034,
Which is greater than upperbound hence we increment by 93. Now iterator is 1349.
log_difference(1349) = 0.08946415071057 which is less than lowerbound.
The next power is 1545 and we need to add 196 to get 1545.
Conditions are as follows:
1) If we find a power whose log_difference() is in the range of
lower and upperbound, we will increment by 196.
which implies that the power is a number which will lead to 123 as starting digits.
2) If we find a power, whose log_difference() is greater than or equal upperbound,
we will increment by 93.
3) if log_difference() < lowerbound, we increment by 196.
Reference to the above logic:
https://math.stackexchange.com/questions/4093970/powers-of-2-starting-with-123-does-a-pattern-exist
>>> solution(1000)
284168
>>> solution(56000)
15924915
>>> solution(678910)
193060223
"""
power_iterator
=
90
position
=
0
lower_limit
=
math
.
log
(
1.23
,
10
)
upper_limit
=
math
.
log
(
1.24
,
10
)
previous_power
=
0
while
position
<
number
:
difference
=
log_difference
(
power_iterator
)
if
difference
>=
upper_limit
:
power_iterator
+=
93
elif
difference
<
lower_limit
:
power_iterator
+=
196
else
:
previous_power
=
power_iterator
power_iterator
+=
196
position
+=
1
return
previous_power
if
__name__
==
"__main__"
:
import
doctest
doctest
.
testmod
()
print
(
f"
{
solution
()
=
}
"
)
You can’t perform that action at this time.