Skip to content

Commit e4ea051

Browse files
committed
P165: Added Java and Python solutions.
Readme: Updated Java SE version requirement from 7 to 8; updated solution count and copyright year.
1 parent 82d6bcb commit e4ea051

File tree

6 files changed

+220
-3
lines changed

6 files changed

+220
-3
lines changed

Answers.txt

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ Problem 155: 3857447
148148
Problem 160: 16576
149149
Problem 162: 3D58725572C62302
150150
Problem 164: 378158756814587
151+
Problem 165: 2868868
151152
Problem 166: 7130034
152153
Problem 169: 178653872807
153154
Problem 171: 142989277

Readme.markdown

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ A collection of Nayuki's program code to solve over 200 Project Euler math probl
55

66
Every solved problem has a program written in Java and usually Python. Some solutions also have Mathematica and Haskell programs. Some solution programs include a detailed mathematical explanation/proof in the comments to justify the code's logic.
77

8-
All problems from #1 to #100 have a Java and Python program, and problems #1 to #50 have a Mathematica program. This package contains at least 200 solutions in Java, at least 200 in Python, at least 125 in Mathematica, and at least 95 in Haskell.
8+
All problems from #1 to #100 have a Java and Python program, and problems #1 to #50 have a Mathematica program. This package contains at least 205 solutions in Java, at least 200 in Python, at least 125 in Mathematica, and at least 95 in Haskell.
99

10-
Java solutions require JDK 7+. Python solutions are tested to work on CPython 3.4.3. Mathematica solutions are tested to work on Mathematica 5.1.
10+
Java solutions require JDK 8+. Python solutions are tested to work on CPython 3.4.3. Mathematica solutions are tested to work on Mathematica 5.1.
1111

1212
Home page with background info, table of solutions, benchmark timings, and more: [https://www.nayuki.io/page/project-euler-solutions](https://www.nayuki.io/page/project-euler-solutions)
1313

1414
----
1515

16-
Copyright © 2020 Project Nayuki. All rights reserved. No warranty.
16+
Copyright © 2021 Project Nayuki. All rights reserved. No warranty.
1717

1818
This code is provided for reference only. You may republish any of this code verbatim with author and URL info intact.
1919

java/EulerTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ public final class EulerTest {
155155
@Test public void testP160() { assertEquals("16576" , new p160().run()); }
156156
@Test public void testP162() { assertEquals("3D58725572C62302" , new p162().run()); }
157157
@Test public void testP164() { assertEquals("378158756814587" , new p164().run()); }
158+
@Test public void testP165() { assertEquals("2868868" , new p165().run()); }
158159
@Test public void testP166() { assertEquals("7130034" , new p166().run()); }
159160
@Test public void testP169() { assertEquals("178653872807" , new p169().run()); }
160161
@Test public void testP171() { assertEquals("142989277" , new p171().run()); }

java/p165.java

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Solution to Project Euler problem 165
3+
* Copyright (c) Project Nayuki. All rights reserved.
4+
*
5+
* https://www.nayuki.io/page/project-euler-solutions
6+
* https://github.com/nayuki/Project-Euler-solutions
7+
*/
8+
9+
import java.math.BigInteger;
10+
import java.util.ArrayList;
11+
import java.util.HashSet;
12+
import java.util.List;
13+
import java.util.Objects;
14+
import java.util.Set;
15+
16+
17+
public final class p165 implements EulerSolution {
18+
19+
public static void main(String[] args) {
20+
System.out.println(new p165().run());
21+
}
22+
23+
24+
private static final int NUM_LINE_SEGMENTS = 5000;
25+
26+
27+
public String run() {
28+
BbsRandom rand = new BbsRandom();
29+
List<LineSegment> lines = new ArrayList<>();
30+
for (int i = 0; i < NUM_LINE_SEGMENTS; i++)
31+
lines.add(new LineSegment(rand));
32+
33+
Set<Point> trueIntersections = new HashSet<>();
34+
Fraction FRAC_ONE = new Fraction(bi(1));
35+
for (int i = 0; i < lines.size(); i++) {
36+
LineSegment seg0 = lines.get(i);
37+
for (int j = i + 1; j < lines.size(); j++) {
38+
LineSegment seg1 = lines.get(j);
39+
40+
int x0 = seg0.x0, y0 = seg0.y0;
41+
int x1 = seg0.x1, y1 = seg0.y1;
42+
int x2 = seg1.x0, y2 = seg1.y0;
43+
int x3 = seg1.x1, y3 = seg1.y1;
44+
45+
// https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line_segment
46+
int denom = (x0 - x1) * (y2 - y3) - (x2 - x3) * (y0 - y1);
47+
if (denom == 0) {
48+
// There is no unique intersection point between the two infinite lines. This is equivalent to
49+
// {one or both line segments being just a point, or both line segments being parallel
50+
// (regardless of whether or not they lie on the same infinite line)}.
51+
continue;
52+
}
53+
int numer0 = (x0 - x2) * (y2 - y3) - (x2 - x3) * (y0 - y2);
54+
int numer1 = (x1 - x0) * (y0 - y2) - (x0 - x2) * (y1 - y0);
55+
56+
Fraction t0 = new Fraction(bi(numer0), bi(denom));
57+
Fraction t1 = new Fraction(bi(numer1), bi(denom));
58+
if (Fraction.ZERO.compareTo(t0) < 0 && t0.compareTo(FRAC_ONE) < 0 &&
59+
Fraction.ZERO.compareTo(t1) < 0 && t1.compareTo(FRAC_ONE) < 0) {
60+
Point p = new Point(
61+
frac(x0).add(t0.multiply(frac(x1 - x0))),
62+
frac(y0).add(t0.multiply(frac(y1 - y0))));
63+
trueIntersections.add(p);
64+
}
65+
}
66+
}
67+
return Integer.toString(trueIntersections.size());
68+
}
69+
70+
71+
private static Fraction frac(int x) {
72+
return new Fraction(bi(x));
73+
}
74+
75+
76+
private static BigInteger bi(int x) {
77+
return BigInteger.valueOf(x);
78+
}
79+
80+
81+
82+
// Blum Blum Shub generator
83+
private static final class BbsRandom {
84+
85+
private int state = 290797;
86+
87+
88+
public int next() {
89+
state = (int)((long)state * state % 50515093);
90+
return state % 500;
91+
}
92+
93+
}
94+
95+
96+
97+
private static final class LineSegment {
98+
99+
public final int x0, y0, x1, y1;
100+
101+
102+
public LineSegment(BbsRandom r) {
103+
x0 = r.next();
104+
y0 = r.next();
105+
x1 = r.next();
106+
y1 = r.next();
107+
}
108+
109+
}
110+
111+
112+
113+
private static final class Point {
114+
115+
private final int xNumer, xDenom, yNumer, yDenom;
116+
117+
118+
public Point(Fraction x, Fraction y) {
119+
xNumer = x.numerator .intValueExact();
120+
xDenom = x.denominator.intValueExact();
121+
yNumer = y.numerator .intValueExact();
122+
yDenom = y.denominator.intValueExact();
123+
}
124+
125+
126+
public boolean equals(Object obj) {
127+
if (!(obj instanceof Point))
128+
return false;
129+
Point other = (Point)obj;
130+
return xNumer == other.xNumer
131+
&& xDenom == other.xDenom
132+
&& yNumer == other.yNumer
133+
&& yDenom == other.yDenom;
134+
}
135+
136+
137+
public int hashCode() {
138+
return Objects.hash(xNumer, xDenom, yNumer, yDenom);
139+
}
140+
141+
}
142+
143+
}

python/eulertest.py

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def main():
179179
160: "16576",
180180
162: "3D58725572C62302",
181181
164: "378158756814587",
182+
165: "2868868",
182183
166: "7130034",
183184
169: "178653872807",
184185
171: "142989277",

python/p165.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#
2+
# Solution to Project Euler problem 165
3+
# Copyright (c) Project Nayuki. All rights reserved.
4+
#
5+
# https://www.nayuki.io/page/project-euler-solutions
6+
# https://github.com/nayuki/Project-Euler-solutions
7+
#
8+
9+
import fractions
10+
11+
12+
def compute():
13+
rand = BbsRandom()
14+
lines = [LineSegment(rand) for _ in range(NUM_LINE_SEGMENTS)]
15+
16+
trueintersections = set()
17+
for (i, seg0) in enumerate(lines):
18+
for seg1 in lines[i + 1 : ]:
19+
x0 = seg0.x0; y0 = seg0.y0
20+
x1 = seg0.x1; y1 = seg0.y1
21+
x2 = seg1.x0; y2 = seg1.y0
22+
x3 = seg1.x1; y3 = seg1.y1
23+
24+
# https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line_segment
25+
denom = (x0 - x1) * (y2 - y3) - (x2 - x3) * (y0 - y1)
26+
if denom == 0:
27+
# There is no unique intersection point between the two infinite lines. This is equivalent to
28+
# {one or both line segments being just a point, or both line segments being parallel
29+
# (regardless of whether or not they lie on the same infinite line)}.
30+
continue
31+
numer0 = (x0 - x2) * (y2 - y3) - (x2 - x3) * (y0 - y2)
32+
numer1 = (x1 - x0) * (y0 - y2) - (x0 - x2) * (y1 - y0)
33+
34+
t0 = fractions.Fraction(numer0, denom)
35+
t1 = fractions.Fraction(numer1, denom)
36+
if 0 < t0 < 1 and 0 < t1 < 1:
37+
trueintersections.add((x0 + t0 * (x1 - x0), y0 + t0 * (y1 - y0)))
38+
39+
return str(len(trueintersections))
40+
41+
42+
NUM_LINE_SEGMENTS = 5000
43+
44+
45+
46+
# Blum Blum Shub generator
47+
class BbsRandom:
48+
49+
def __init__(self):
50+
self.state = 290797
51+
52+
53+
def next(self):
54+
self.state *= self.state
55+
self.state %= 50515093
56+
return self.state % 500
57+
58+
59+
60+
class LineSegment:
61+
62+
def __init__(self, r):
63+
self.x0 = r.next()
64+
self.y0 = r.next()
65+
self.x1 = r.next()
66+
self.y1 = r.next()
67+
68+
69+
70+
if __name__ == "__main__":
71+
print(compute())

0 commit comments

Comments
 (0)