Skip to content

Commit 52d257a

Browse files
committed
Kotlin - Chapter 19: Math and Geometry
* Josephus * Maximum Collinear Points * Reverse 32 Bits Integer * Spiral Matrix * Triangle Numbers
1 parent 795c6b1 commit 52d257a

File tree

6 files changed

+149
-0
lines changed

6 files changed

+149
-0
lines changed

kotlin/Math and Geometry/Josephus.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fun josephus(n: Int, k: Int): Int {
2+
// Base case: If there's only one person, the last person is person 0.
3+
if (n == 1) {
4+
return 0
5+
}
6+
// Calculate the position of the last person remaining in the reduced problem
7+
// with 'n - 1' people. We use modulo 'n' to ensure the answer doesn't exceed
8+
// 'n - 1'.
9+
return (josephus(n - 1, k) + k) % n
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fun josephusOptimized(n: Int, k: Int): Int {
2+
var res = 0
3+
for (i in 2..n) {
4+
// res[i] = (res[i - 1] + k) % i.
5+
res = (res + k) % i
6+
}
7+
return res
8+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import
2+
3+
fun maximumCollinearPoints(points: List<List<Int>>): Int {
4+
var res = 0
5+
// Treat each point as a focal point, and determine the maximum
6+
// number of points that are collinear with each focal point. The
7+
// largest of these maximums is the answer.
8+
for (i in points.indices) {
9+
res = maxOf(res, maxPointsFromFocalPoint(i, points))
10+
}
11+
return res
12+
}
13+
14+
fun maxPointsFromFocalPoint(focalPointIndex: Int, points: List<List<Int>>): Int {
15+
val slopesMap = mutableMapOf<Pair<Int, Int>, Int>()
16+
var maxPoints = 0
17+
// For the current focal point, calculate the slope between it and
18+
// every other point. This allows us to group points that share the
19+
// same slope.
20+
for (j in points.indices) {
21+
if (j != focalPointIndex) {
22+
val currSlope = getSlope(points[focalPointIndex], points[j])
23+
slopesMap[currSlope] = slopesMap.getOrDefault(currSlope, 0) + 1
24+
// Update the maximum count of collinear points for the
25+
// current focal point.
26+
maxPoints = maxOf(maxPoints, slopesMap[currSlope]!!)
27+
}
28+
}
29+
// Add 1 to the maximum count to include the focal point itself.
30+
return maxPoints + 1
31+
}
32+
33+
fun getSlope(p1: List<Int>, p2: List<Int>): Pair<Int, Int> {
34+
val rise = p2[1] - p1[1]
35+
val run = p2[0] - p1[0]
36+
// Handle vertical lines separately to avoid dividing by 0.
37+
if (run == 0) {
38+
return Pair(1, 0)
39+
}
40+
// Simplify the slope to its reduced form.
41+
val gcdVal = gcd(rise, run)
42+
return Pair(rise / gcdVal, run / gcdVal)
43+
}
44+
45+
// Kotlin doesn't have a built-in GCD function, so we define one here.
46+
fun gcd(a: Int, b: Int): Int {
47+
var num1 = a
48+
var num2 = b
49+
while (num2 != 0) {
50+
val temp = num2
51+
num2 = num1 % num2
52+
num1 = temp
53+
}
54+
return num1
55+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
fun reverse32BitInteger(n: Int): Int {
2+
// shadow n to make it mutable
3+
var n = n
4+
val intMax = Int.MAX_VALUE
5+
val intMin = Int.MIN_VALUE
6+
var reversedN = 0
7+
// Keep looping until we've added all digits of 'n' to 'reversedN'
8+
// in reverse order.
9+
while (n != 0) {
10+
// digit = n % 10
11+
val digit = n % 10
12+
// n = n / 10
13+
n /= 10
14+
// Check for integer overflow or underflow.
15+
if (reversedN > (intMax / 10) || reversedN < (intMin / 10)) {
16+
return 0
17+
}
18+
// Add the current digit to 'reversedN'.
19+
reversedN = reversedN * 10 + digit
20+
}
21+
return reversedN
22+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
fun spiralMatrix(matrix: List<List<Int>>): List<Int> {
2+
if (matrix.isEmpty()) {
3+
return emptyList()
4+
}
5+
val result = mutableListOf<Int>()
6+
// Initialize the matrix boundaries.
7+
var top = 0
8+
var bottom = matrix.size - 1
9+
var left = 0
10+
var right = matrix[0].size - 1
11+
// Traverse the matrix in spiral order.
12+
while (top <= bottom && left <= right) {
13+
// Move from left to right along the top boundary.
14+
for (i in left..right) {
15+
result.add(matrix[top][i])
16+
}
17+
top++
18+
// Move from top to bottom along the right boundary.
19+
for (i in top..bottom) {
20+
result.add(matrix[i][right])
21+
}
22+
right--
23+
// Check that the bottom boundary hasn't passed the top boundary
24+
// before moving from right to left along the bottom boundary.
25+
if (top <= bottom) {
26+
for (i in right downTo left) {
27+
result.add(matrix[bottom][i])
28+
}
29+
bottom--
30+
}
31+
// Check that the left boundary hasn't passed the right boundary
32+
// before moving from bottom to top along the left boundary.
33+
if (left <= right) {
34+
for (i in bottom downTo top) {
35+
result.add(matrix[i][left])
36+
}
37+
left++
38+
}
39+
}
40+
return result
41+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun triangleNumbers(n: Int): Int {
2+
// If n is an odd-numbered row, the first even number always starts at position
3+
// 2.
4+
if (n % 2 != 0) {
5+
return 2
6+
}
7+
// If n is a multiple of 4, the first even number always starts at position 3.
8+
else if (n % 4 == 0) {
9+
return 3
10+
}
11+
// For all other rows, the first even number always starts at position 4.
12+
return 4
13+
}

0 commit comments

Comments
 (0)