Skip to content

Commit

Permalink
Small refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
ashtanko committed Mar 19, 2024
1 parent 8fa8c54 commit 07d1efa
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 49 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@

## Metrics

* 11,099 number of properties
* 11,102 number of properties

* 7,652 number of functions
* 7,655 number of functions

* 7,097 number of classes

Expand All @@ -32,15 +32,15 @@

## Complexity Report

* 182,944 lines of code (loc)
* 182,960 lines of code (loc)

* 112,136 source lines of code (sloc)
* 112,151 source lines of code (sloc)

* 79,786 logical lines of code (lloc)
* 79,797 logical lines of code (lloc)

* 50,329 comment lines of code (cloc)
* 50,328 comment lines of code (cloc)

* 18,830 cyclomatic complexity (mcc)
* 18,833 cyclomatic complexity (mcc)

* 16,439 cognitive complexity

Expand All @@ -54,4 +54,4 @@

## Findings (0)

generated with [detekt version 1.23.5](https://detekt.dev/) on 2024-03-18 17:13:10 UTC
generated with [detekt version 1.23.5](https://detekt.dev/) on 2024-03-19 10:53:09 UTC
3 changes: 3 additions & 0 deletions config/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
| Properties | Functions | Classes | Packages | Kotlin files |
|------------|-----------|---------|----------|--------------|
| @{props} | @{funcs} | @{clss} | @{pckg} | @{ktf} |
1 change: 1 addition & 0 deletions src/main/kotlin/dev/shtanko/algorithms/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const val ALPHABET_LETTERS_COUNT = 26
const val HALF = 0.5f
const val THREE_HALVES = 1.5F
const val QUEEN = 'Q'
const val ASCII_A = 'A'
const val DOT = '.'
const val VOWELS = "aeiou"
const val TOLERANCE = 1e-10
97 changes: 56 additions & 41 deletions src/main/kotlin/dev/shtanko/algorithms/leetcode/TaskScheduler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,70 +17,85 @@
package dev.shtanko.algorithms.leetcode

import dev.shtanko.algorithms.ALPHABET_LETTERS_COUNT
import dev.shtanko.algorithms.ASCII_A
import java.util.PriorityQueue
import kotlin.math.max

fun interface TaskScheduler {
operator fun invoke(tasks: CharArray, n: Int): Int
operator fun invoke(tasks: CharArray, cooldownTime: Int): Int
}

class TaskSchedulerSimple : TaskScheduler {

override operator fun invoke(tasks: CharArray, n: Int): Int {
val counter = IntArray(ALPHABET_LETTERS_COUNT)
var max = 0
var maxCount = 0
override operator fun invoke(tasks: CharArray, cooldownTime: Int): Int {
val taskFrequencyCounter = IntArray(ALPHABET_LETTERS_COUNT)
var maxFrequency = 0
var maxFrequencyCount = 0
for (task in tasks) {
counter[task - 'A']++
if (max == counter[task - 'A']) {
maxCount++
} else if (max < counter[task - 'A']) {
max = counter[task - 'A']
maxCount = 1
taskFrequencyCounter[task - ASCII_A]++
if (maxFrequency == taskFrequencyCounter[task - ASCII_A]) {
maxFrequencyCount++
} else if (maxFrequency < taskFrequencyCounter[task - ASCII_A]) {
maxFrequency = taskFrequencyCounter[task - ASCII_A]
maxFrequencyCount = 1
}
}

val partCount = max - 1
val partLength = n - maxCount.minus(1)
val emptySlots = partCount * partLength
val availableTasks: Int = tasks.size - max * maxCount
val idles = max(0, emptySlots - availableTasks)
val numberOfParts = maxFrequency - 1
val partLength = cooldownTime - maxFrequencyCount + 1
val emptySlots = numberOfParts * partLength
val availableTasks: Int = tasks.size - maxFrequency * maxFrequencyCount
val idleSlots = max(0, emptySlots - availableTasks)

return tasks.size + idles
return tasks.size + idleSlots
}
}

class TaskSchedulerPriorityQueue : TaskScheduler {
override operator fun invoke(tasks: CharArray, n: Int): Int {
val map: MutableMap<Char, Int> = HashMap()
for (i in tasks.indices) {
map[tasks[i]] =
map.getOrDefault(tasks[i], 0) + 1 // map key is TaskName, and value is number of times to be executed.
override operator fun invoke(tasks: CharArray, cooldownTime: Int): Int {
val taskFrequencyMap = calculateTaskFrequency(tasks)
val taskPriorityQueue = createPriorityQueue(taskFrequencyMap)

return executeTasksWithCooldown(taskPriorityQueue, cooldownTime)
}

private fun calculateTaskFrequency(tasks: CharArray): MutableMap<Char, Int> {
val taskFrequencyMap: MutableMap<Char, Int> = HashMap()
for (task in tasks) {
taskFrequencyMap[task] = taskFrequencyMap.getOrDefault(task, 0) + 1
}
return taskFrequencyMap
}

val q: PriorityQueue<Map.Entry<Char, Int>> =
private fun createPriorityQueue(taskFrequencyMap: MutableMap<Char, Int>): PriorityQueue<Map.Entry<Char, Int>> {
val taskPriorityQueue: PriorityQueue<Map.Entry<Char, Int>> =
PriorityQueue { a, b -> if (a.value != b.value) b.value - a.value else a.key - b.key }
taskPriorityQueue.addAll(taskFrequencyMap.entries)
return taskPriorityQueue
}

q.addAll(map.entries)

var count = 0
while (q.isNotEmpty()) {
var k = n + 1
val tempList: MutableList<Map.Entry<Char, Int>> = ArrayList()
while (k > 0 && q.isNotEmpty()) {
val top: MutableMap.MutableEntry<Char, Int> =
q.poll() as MutableMap.MutableEntry<Char, Int> // most frequency task
top.setValue(top.value - 1) // decrease frequency, meaning it got executed
tempList.add(top) // collect task to add back to queue
k--
count++ // successfully executed task
private fun executeTasksWithCooldown(
taskPriorityQueue: PriorityQueue<Map.Entry<Char, Int>>,
cooldownTime: Int,
): Int {
var taskExecutions = 0
while (taskPriorityQueue.isNotEmpty()) {
var cooldown = cooldownTime + 1
val temporaryTaskList: MutableList<Map.Entry<Char, Int>> = ArrayList()
while (cooldown > 0 && taskPriorityQueue.isNotEmpty()) {
val mostFrequentTask: MutableMap.MutableEntry<Char, Int> =
taskPriorityQueue.poll() as MutableMap.MutableEntry<Char, Int> // most frequency task
mostFrequentTask.setValue(mostFrequentTask.value - 1) // decrease frequency, meaning it got executed
temporaryTaskList.add(mostFrequentTask) // collect task to add back to queue
cooldown--
taskExecutions++ // successfully executed task
}
for (e in tempList) {
if (e.value > 0) q.add(e) // add valid tasks
for (entry in temporaryTaskList) {
if (entry.value > 0) taskPriorityQueue.add(entry) // add valid tasks
}
if (q.isEmpty()) break
count += k // if k > 0, then it means we need to be idle
if (taskPriorityQueue.isEmpty()) break
taskExecutions += cooldown // if cooldown > 0, then it means we need to be idle
}
return count
return taskExecutions
}
}

0 comments on commit 07d1efa

Please sign in to comment.