kotlin coding test course, Euler PI

1. What is the Euler Problem?

Leonardo Euler was a mathematician who made many contributions to various fields of mathematics. The Euler problems, named after him, are primarily problems that require mathematical thinking and algorithmic approaches. These problems often focus on discovering ways to perform various calculations based on simple mathematical concepts.

2. Example of Euler Problem – Problem 1: Find the sum of all natural numbers from 1 to 1000 that are multiples of 3 or 5

To clearly understand the problem, let’s restate it.
We want to find the numbers from 1 to 1000 that are divisible by 3 or 5 and calculate their sum.

3. Problem-solving Approach

This problem can be solved using simple loops and conditional statements.
The following approach can be considered.

  1. Iterate through all natural numbers from 1 to 1000.
  2. Check if each number is divisible by 3 or 5.
  3. Sum the numbers that meet the criteria.
  4. Print the final result.

4. Implementing in Kotlin

Now, let’s solve the problem with Kotlin code according to the above approach.

fun main() {
        var sum = 0
        for (i in 1 until 1000) {
            if (i % 3 == 0 || i % 5 == 0) {
                sum += i
            }
        }
        println("The sum of natural numbers from 1 to 1000 that are multiples of 3 or 5 is: $sum")
    }

4.1 Explanation of the Code

The above code is structured as follows:

  • var sum = 0: Initializes a variable to store the sum.
  • for (i in 1 until 1000): Iterates from 1 to 999. The until keyword is used so that 1000 is not included.
  • if (i % 3 == 0 || i % 5 == 0): Checks if the current number is a multiple of 3 or 5.
  • sum += i: Adds the current number to the sum if it meets the condition.
  • println(...): Prints the final result.

5. Execution Result

When the program is run, you can obtain the following result:


    The sum of natural numbers from 1 to 1000 that are multiples of 3 or 5 is: 233168
    

6. Additional Lessons Learned

Through this problem, we can learn a few important points:

  • Step-by-step thought process for problem-solving.
  • Effective use of conditional statements and loops.
  • How to output results.

7. Extension of the Problem

This problem can be extended in several different ways. For example, you can change 1000 to 10000 or try using different numbers other than 3 and 5. Changing the scope of the problem can also provide more practice.

8. Conclusion

In this article, we explored how to solve the Euler problem using Kotlin. Algorithmic problems are great practice for improving various problem-solving skills. I hope you continue to solve various problems and gain experience.

9. References

Kotlin Coding Test, Finding the Sum of Consecutive Natural Numbers

Problem Description

The problem of finding the sum of consecutive natural numbers is a common topic in coding tests.
Given the input integer N, the problem is to find M such that the sum of consecutive natural numbers from 1 to M equals N. Here, M must be a natural number greater than or equal to 1, and the sum of consecutive natural numbers can be calculated using the following formula:

S = 1 + 2 + 3 + ... + M = M * (M + 1) / 2

Input

– Integer N (1 ≤ N ≤ 1,000,000) – the sum of natural numbers to be found

Output

– Output M when the sum of consecutive natural numbers from 1 to M equals N.
– If M does not exist, output -1.

Approach to Problem

To solve this problem, it is useful to first rewrite the condition S = N into an equation.
When setting S = 1 + 2 + ... + M equal to N, rearranging gives us:

N = M * (M + 1) / 2

The above equation can be transformed to 2N = M * (M + 1).
We can then solve for M using this equation and check if the value is a natural number.

Solution Process

1. To find possible M for N, start with M equal to 1 and increase it while calculating S.
2. If S equals N, print M and terminate.
3. If S exceeds N, there is no need to search further, print -1 and terminate.

Code Implementation

Below is the code that implements the above logic in Kotlin.

fun findContinuousNaturalSum(N: Int): Int {
        var sum = 0
        for (M in 1..N) {
            sum += M
            if (sum == N) {
                return M
            } else if (sum > N) {
                return -1
            }
        }
        return -1
    }

    fun main() {
        val N = 15
        val result = findContinuousNaturalSum(N)
        println("The value of M such that the sum of consecutive natural numbers equals $N is: $result")
    }

Code Explanation

– The findContinuousNaturalSum function finds M such that the sum of consecutive natural numbers equals
N.
– The sum variable stores the sum from 1 to M.
– Using a for loop, M is incremented from 1 to N, while calculating sum.
– If sum equals N, M is returned, and if sum exceeds N, -1 is returned to terminate.

Examples

Input: 15
Output: 5
Explanation: 1+2+3+4+5 = 15, so M is 5.

Input: 14
Output: -1
Explanation: There is no case where the sum from 1 to M equals 14.

Conclusion

The problem of finding the sum of consecutive natural numbers is an important one that effectively utilizes basic loops and conditional statements in programming.
Through this problem, you can enhance your understanding of basic syntax and logic construction in Kotlin, which is beneficial for learning approaches to algorithmic problem-solving.
It is recommended to practice these fundamental problems sufficiently to solve a variety of future problems.

Kotlin Coding Test Course, Finding the Sum of Consecutive Numbers

Problem Description

Given an integer array arr, this is a problem of finding the maximum sum of a contiguous subarray.
In other words, you need to determine what the largest sum is when adding up a few consecutive numbers from arr.
This problem is one of the frequently asked coding test questions and can be solved using Kadane’s algorithm.

Problem Example

Input

[2, -1, 3, 4, -2, 1, -5, 4]

Output

10

Explanation: The sum of the contiguous subarray [3, 4, -2, 1] is the maximum at 10.

Approach to the Problem

Since this problem requires finding the sum of a contiguous subarray, the key is how to set the range.
That is, while you can approach this by fixing starting and ending points and summing all elements in between,
this method is inefficient. Instead, you can solve it in O(n) time complexity using Kadane’s algorithm.

Kadane’s Algorithm

Kadane’s algorithm works by updating the maximum sum of the contiguous subarray so far by comparing it to the current position’s value.
The specific steps are as follows:

  1. Initialize the variables maxSoFar and maxEndingHere. Both can be initialized to 0 or the first element of the array.
  2. Traverse the array and add the current value arr[i] to maxEndingHere.
  3. If maxEndingHere is greater than maxSoFar, update maxSoFar.
  4. If maxEndingHere becomes less than 0, reset it to 0 to start a new contiguous sum.

This method can find the maximum sum in O(n) time, regardless of the array size.

Kotlin Code Implementation

Below is the code that implements the above algorithm in Kotlin:


fun maxSubArraySum(arr: IntArray): Int {
    var maxSoFar = arr[0]
    var maxEndingHere = arr[0]

    for (i in 1 until arr.size) {
        maxEndingHere = Math.max(arr[i], maxEndingHere + arr[i])
        maxSoFar = Math.max(maxSoFar, maxEndingHere)
    }

    return maxSoFar
}

fun main() {
    val arr = intArrayOf(2, -1, 3, 4, -2, 1, -5, 4)
    val result = maxSubArraySum(arr)
    println("Maximum contiguous sum: $result")
}
        

The above code defines a function maxSubArraySum that calculates the maximum contiguous sum from a given integer array.

Time Complexity Analysis

Since Kadane’s algorithm derives results through a single traversal of the array, its time complexity is O(n).
Therefore, increasing the size of the array does not significantly affect performance. The space complexity is O(1) and is very efficient as it does not use any additional data structures.

Conclusion

The problem of finding contiguous sums is a frequently encountered issue in algorithm problem solving,
and can be efficiently solved through Kadane’s algorithm. This allows you to learn the basics of Kotlin syntax and algorithm design at the same time.
Since this is a problem that often appears in coding tests, practice it to be able to implement it naturally.

Additional Practice Problems

Try additional practice with the following modified problems:

  • Write a program that outputs both the starting and ending indices of the contiguous subarray from the given array.
  • Find the maximum contiguous sum when given an array with all negative elements.
  • Create a program that receives multiple test cases and outputs the maximum contiguous sum for each.

References

Kotlin Coding Test, Counting the Number of Connected Components

Hello! Today, I am going to solve a coding test problem using Kotlin. The topic is “Counting the Number of Connected Components”. This problem requires an understanding of graph theory and DFS (Depth-First Search) or BFS (Breadth-First Search). Through this problem, we will expand our concepts about graphs and connected components.

Problem Description

Given the number of vertices N and the number of edges M, an undirected graph with N vertices is provided. Write a program to count the number of connected components in this graph. A connected component refers to a set of vertices that are connected to each other.

Input

  • The first line contains the number of vertices N (1 ≤ N ≤ 1000) and the number of edges M (0 ≤ M ≤ 10000).
  • The next M lines contain information about the edges. (Vertex A, Vertex B, 1 ≤ A, B ≤ N)

Output

  • Output the number of connected components.

Example Input

6 5
1 2
2 5
5 1
3 4
6 2

Example Output

2

Solution Process

To solve this problem, we can use DFS (or BFS) to explore all connected components of the graph. This way, we can visit each connected component once and increase the count. The entire process is as follows.

1. Graph Representation

First, we represent the graph using an adjacency list. An adjacency list maintains a list of connected vertices for each vertex. To do this, we create an empty list and add the connected vertices for each vertex. In Kotlin, we can use MutableList.

2. Implementing the DFS Function

We implement a function that explores the graph using DFS. This function visits a specific vertex and recursively visits all vertices connected to it. The visited vertices are marked to avoid duplicate visits later.

3. Connected Component Count

We call DFS for all vertices to count the number of connected components. If DFS is called, we increase the count.

Code Implementation

Now let’s implement the above process in code. Below is the code written in Kotlin.

fun main() {
    val (n, m) = readLine()!!.split(" ").map { it.toInt() }
    val graph = MutableList(n + 1) { mutableListOf() }

    for (i in 0 until m) {
        val (a, b) = readLine()!!.split(" ").map { it.toInt() }
        graph[a].add(b)
        graph[b].add(a)
    }

    val visited = BooleanArray(n + 1)
    var count = 0

    fun dfs(vertex: Int) {
        visited[vertex] = true
        for (neighbor in graph[vertex]) {
            if (!visited[neighbor]) {
                dfs(neighbor)
            }
        }
    }

    for (i in 1..n) {
        if (!visited[i]) {
            dfs(i)
            count++
        }
    }

    println(count)
}

4. Time Complexity Analysis

The time complexity of this algorithm is O(N + M). Here, N is the number of vertices, and M is the number of edges. Hence, it is proportional to the time taken to visit the graph once and explore all edges.

Conclusion

Through this lecture, we have learned how to solve the problem of counting the number of connected components. Understanding and utilizing the basics of graph theory and DFS/BFS is very important for coding tests. Solidifying the foundation of this algorithm will greatly help in solving various problems.

I hope to further solidify the theory through practice problems and work hard to prepare for coding tests. See you in the next lecture!

Sign up for Kotlin coding test course, planning a trip

Problem Description

When planning a trip, we need to consider the time and cost required to travel between several cities. Let’s solve the problem of creating an optimal travel plan based on the information provided below.

Problem: Travel Route Optimization

You are given a graph representing N cities and the travel time/cost between each pair of cities. Write a program to calculate the optimal route that starts from the initial city, visits all cities in minimum time or cost, and returns to the starting city.

Input

  • The first line contains the number of cities N (1 ≤ N ≤ 12).
  • Next, an N x N matrix is provided where each element represents the travel time (or cost) between two cities. If travel is not possible, it is represented by -1.

Output

Print the minimum travel time (or cost).

Example

Input:
4
0 10 15 20
10 0 -1 25
15 -1 0 30
20 25 30 0

Output:
75

Problem Solving Process

1. Understanding the Problem

This problem involves finding a path that minimizes the travel time between the given cities. This is commonly known as the Traveling Salesman Problem (TSP), which is an NP-hard problem. The input graph is represented as an adjacency matrix, and we need to explore the optimal route based on this matrix.

2. Approach

To solve this problem, we will combine Depth-First Search (DFS) with a Dynamic Programming (DP) technique using bit masking. Bit masking allows us to efficiently represent the state of visited cities and helps avoid redundant calculations.

3. Kotlin Implementation

        
        fun findMinCost(graph: Array, visited: Int, pos: Int, n: Int, memo: Array): Int {
            // If all cities have been visited
            if (visited == (1 shl n) - 1) {
                return graph[pos][0] // Return to the starting city
            }

            // Memoization check
            if (memo[visited][pos] != -1) {
                return memo[visited][pos]
            }

            var ans = Int.MAX_VALUE

            // Explore all cities
            for (city in 0 until n) {
                // If not visited and travel is possible
                if ((visited and (1 shl city)) == 0 && graph[pos][city] != -1) {
                    val newCost = graph[pos][city] + findMinCost(graph, visited or (1 shl city), city, n, memo)
                    ans = Math.min(ans, newCost)
                }
            }

            // Save in memoization
            memo[visited][pos] = ans
            return ans
        }

        fun tsp(graph: Array, n: Int): Int {
            // Initialization
            val memo = Array(1 shl n) { IntArray(n) { -1 } }
            return findMinCost(graph, 1, 0, n, memo)
        }

        fun main() {
            val graph = arrayOf(
                intArrayOf(0, 10, 15, 20),
                intArrayOf(10, 0, -1, 25),
                intArrayOf(15, -1, 0, 30),
                intArrayOf(20, 25, 30, 0)
            )
            val n = graph.size
            val result = tsp(graph, n)
            println("Minimum travel cost: $result")
        }
        
    

4. Code Explanation

The above code shows the overall flow of the algorithm for optimizing the travel route. The main parts are as follows:

  • findMinCost: Takes the current city and the state of visited cities as parameters and recursively calculates the minimum cost.
  • tsp: Calculates the overall minimum cost using bit masking and memoization.

5. Performance Analysis

This code has a time complexity of O(N^2 * 2^N), where N is the number of cities. This is due to the nature of searching all paths with DFS and the feature of storing visited states using bit masking. It is practically executable for inputs with up to 12 cities, making it efficient for reasonably sized inputs.

Conclusion

Through the travel planning algorithm problem, we have learned how to utilize Dynamic Programming techniques with DFS and bit masking. This is a valuable skill for coding tests and algorithm challenges, so be sure to master it. Keep improving your algorithm skills through various problems!