- Less code is better. Keep code dense. Code is a liability, not an asset
- I prefer working on Kotlin/JVM projects that are built around core principles like type soundness, loosely coupled components, dependency injection, composition, and delegation.
- I completely avoid projects that heavily rely on oop implementation inheritance for code reuse or extensibility, or where static functions are the main tool for implementing business logic, or where JPA/Hibernate is used for complex read operations.
- I prioritize delivering correct and long-term maintainable systems.
- Actively used skills: Kotlin, Java, SQL, Git, Spring Framework, Gradle, REST, PostgreSQL, Firestore, Apigee, Data-Oriented Programming (DOP), Component-Oriented Programming (COP), Dependency Injection, Data Structures and Algorithms, Agentic AI.
- Key business domains: E-commerce, Financial Services and Insurance Technology.
- Skilled in implementing new features, fixing bugs, code reviewing, providing documentation for developers, reducing technical debt growth, analyzing codebases, ensuring compliance with coding standards, unifying codebases for DOP programming style.
- Strong track record in refactoring codebases, restructuring code into composable and reusable elements, thus enhancing the maintainability and adaptability of applications in the long run.
- Experience in analyzing modular codebases to map data flows, clarify and document field mappings, document legacy and cloud-based systems.
- Experience in API development, including creating Apigee proxies, implementing rate limiting and delivering comprehensive OpenAPI documentation.
- Adhere to best software design practices, with a strong preference for "Composition over inheritance" principle.
- Experience in CI/CD pipeline management, including migration from Jenkins to GitLab CI/CD.
- My code is structured into components: https://github.com/Sedose/codecrafters-interpreter-kotlin.
- Google Cloud Platform Professional Cloud Developer (GCP PCD) certified.
- Hold bachelor's and master's degree in Computer Science & Programming Engineering.
In programming:
- Prefer user defined records/ data classes/ case classes, etc. over Triple/ Tuple/ Pair, Map Entry etc.
- Prefer composition/ aggregation, delegation, dependency injection over inheritance.
- Use destructuring where applicable isntead of manually grab components from struct, data classes, etc.
- Do not write comments and docs unless we do need it or code already was with this - preserve it.
- Use descriptive variable/ function names! Do not name them as short abbreviations!
- Use data oriented programming (ADTs) where suitable
- Do not care about unit tests unless I explicitely asked to do so.
- Minimize Abstractions: Prefer the simplest viable path; avoid mapping or indirection unless there is a clear downstream need (explain when kept).
- Mapping Format: When asked for field mappings, respond in a clear table with columns
Source → Intermediate → Response, and explicitly state when a field is not propagated. - Embrace Refactoring to Simplicity: Actively look for opportunities to refactor the code towards a simpler, more direct implementation that removes unnecessary layers of indirection, in line with my programming philosophy. For example, prefer direct string formatting for building queries over using intermediate variables if it results in clearer, denser code.
- Partial Results Handling: When adding pagination, explicitly decide (and document) whether to return partial data and whether to cache partials; prefer encoding completeness in a sum type/ADT over boolean flags.
- Cache Discipline on Partial: Do not backfill cache when pagination returns partial results; allow subsequent calls to retry for completeness.
- Pagination Observability: If partial results are possible, emit a single warning with the last successful offset/page for ops visibility.
- Data Reality Before Complexity: Before implementing complex logic, verify data-layer reality (run or request queries) to confirm the need; if the data does not exceed limits, avoid adding code (code is a liability).
- Prefer iterations of small code changes, rather than complete rewrite
- Do not try to run tests, do not try to run build, do not care about tests unless I explcitly ask for
- Confirm Understanding Before Editing: Before writing or changing code, summarize my understanding of the task, including the target behavior, relevant constraints, and what I will intentionally avoid changing. If anything is ambiguous, ask before coding; otherwise proceed directly with the smallest safe change.
- Pipeline programming
- Data-oriented programming
- Functional-like programming
- Declarative-like programming
- Side-effect isolation (I/O only in
main) - Expression-oriented programming
- Structured, composable functions
- No mutable global state
- Prefer not to have even local mutable state unless absolutely needed to gain smth much more valuable
- Prefer not to have explicit
source code-level loops unless absolutely needed to gain smth much more valuable - Pure functions
- Minimal branching, maximal transformation
- Clean, predictable control flow
- Lean functional patterns
- Less code means better. Keep code dense. Code is a liability, not an asset
- The code is not opimized to gain maximum raw speed
- The code is kept vertical, so it stays within a regular monitor size, no need for endless zooming, scroling nonsense
- The code is opimized for correctness, simplicity and clarity
- The code is straightforward like do 1, do 2, do 3, get result
- Place expressions to a next line, and not the same line as = Example:
- DO NOT DO THIS: String logMessage = isEmpty(restaurantGroups) ? "Backfilling cache with empty restaurant groups list: identifier={}, keySuffix={}" : "Backfilling cache for restaurant groups: identifier={}, keySuffix={}";
- DO THIS: String logMessage = isEmpty(restaurantGroups) ? "Backfilling cache with empty restaurant groups list: identifier={}, keySuffix={}" : "Backfilling cache for restaurant groups: identifier={}, keySuffix={}";
- Prefer small, single‑purpose components over multi‑responsibility classes; For example, split orchestration, query building, and parsing into dedicated units when a class starts doing multiple concerns.
- Prefer Lombok
@RequiredArgsConstructorover hand-written constructors for dependency injection. - Prefer static collection helpers from libraries over inline size/empty checks (e.g.,
isEmpty(list)instead oflist.isEmpty()/list.size() == 0). - Prefer
String::formatted(or"pattern".formatted(value)) for simple string templating instead of manual concatenation. - Avoid naming components with
Factory(prefer neutral names like Builder/Composer/Assembler). - Standardize on Apache Commons Collections4 helpers (avoid Spring
CollectionUtilsand commons-collections v3). - Prefer static imports for Apache Commons
StringUtilspredicates (isBlank/isNotBlank). - Standardize all null/empty guards with Apache Commons
ObjectUtils.isEmpty/isNotEmpty. - Use
normalize*naming for sanitized collections/values (avoidsafe*). - Prefer method references over lambdas when readable.
- Avoid negated-condition patterns when feasible; prefer positive predicates or helper methods (e.g.,
isNotEmpty(list)instead of!isEmpty(list),isNotBlank(value)instead of!isBlank(value)). - Always enable pretty-printed JSON logs for Spring Boot console output (e.g.,
logback-spring.xml); apply the closest equivalent for other tech stacks. - Prefer
application.ymlfor local setup defaults unless there is a clear profile-specific need.
private const val DIAL_UPPER_BOUND = 100
fun main() {
(
object {}.javaClass
.getResource("/day1_part1.txt")
?.readText()
?: error("Resource not found")
)
.lineSequence()
.map(String::trim)
.filter(String::isNotEmpty)
.map(::parseMoveDelta)
.scan(50, ::nextPosition)
.count { it == 0 }
.let(::println)
}
fun parseMoveDelta(text: String): Int {
val amount = text.drop(1).toInt()
return when (text.first()) {
'L' -> -amount
'R' -> amount
else -> 0
}
}
fun nextPosition(position: Int, delta: Int): Int =
(position + delta).mod(DIAL_UPPER_BOUND)import scala.io.Source
import scala.util.Using
import scala.util.chaining.scalaUtilChainingOps
private val DIAL_UPPER_BOUND = 100
@main def main(): Unit =
Using.resource(Source.fromResource("day1_part1.txt"))(_.mkString)
.linesIterator
.map(_.trim)
.filter(_.nonEmpty)
.map(parseMoveDelta)
.scanLeft(50)(nextPosition)
.count(_ == 0)
.pipe(println)
def parseMoveDelta(text: String): Int =
val amount = text.drop(1).toInt
text.head match
case 'L' => -amount
case 'R' => amount
case _ => 0
def nextPosition(position: Int, delta: Int): Int =
Math.floorMod(position + delta, DIAL_UPPER_BOUND)import static com.example.Input.INPUT;
void main() {
int dialUpperBound = 100;
long password =
INPUT.stripIndent()
.lines()
.map(String::trim)
.filter(line -> !line.isEmpty())
.map(this::parseMoveDelta)
.gather(Gatherers.scan(
() -> 50,
(position, delta) -> Math.floorMod(position + delta, dialUpperBound)
))
.filter(it -> 0 == it)
.count();
IO.println(password);
}
private int parseMoveDelta(String text) {
int amount = Integer.parseInt(text.substring(1));
return switch (text.charAt(0)) {
case 'L' -> -amount;
case 'R' -> amount;
default -> 0;
};
}use std::fs;
use std::ops::Not;
const DIAL_UPPER_BOUND: i32 = 100;
fn main() {
let password = fs::read_to_string("day1_part1.txt")
.unwrap_or("".to_string())
.lines()
.map(str::trim)
.filter(|line| line.is_empty().not())
.map(parse_move_delta)
.scan(50, next_position)
.filter(|position| *position == 0)
.count();
println!("{password}");
}
fn parse_move_delta(text: &str) -> i32 {
let (direction, amount_text) = text.split_at(1);
let amount: i32 = amount_text.parse().unwrap_or(0);
match direction {
"L" => -amount,
"R" => amount,
_ => 0,
}
}
fn next_position(position: &mut i32, delta: i32) -> Option<i32> {
*position = (*position + delta).rem_euclid(DIAL_UPPER_BOUND);
Some(*position)
}const input = "
R22
L2
R13
L49
...
L7
L12
L35
R50
"
pub fn main() {
input
|> string.split("\n")
|> list.map(string.trim)
|> list.filter(fn(s) { s != "" })
|> calculate_password
|> int.to_string
|> io.println
}
const dial_upper_bound = 100
fn calculate_password(input: List(String)) -> Int {
input
|> list.map(parse_move_delta)
|> list.scan(50, next_position)
|> list.count(fn(pos) { pos == 0 })
}
fn next_position(position, delta) -> Int {
let new_pos = position + delta
new_pos % dial_upper_bound
}
fn parse_move_delta(text: String) -> Int {
let amount =
text
|> string.drop_start(1)
|> int.parse
|> result.unwrap(0)
case string.first(text) {
Ok("L") -> -amount
Ok("R") -> amount
_ -> 0
}
}module Main where
import Data.Function ((&))
import Data.Char (isSpace)
import Data.List ( scanl', dropWhileEnd )
import Data.Maybe (fromMaybe)
dialUpperBound :: Int
dialUpperBound = 100
initialPosition :: Int
initialPosition = 50
main :: IO ()
main =
readFile "day1_part1.txt" >>= \contents ->
contents
& lines
& map trim
& filter (not . null)
& concatMap parseIndividualClicks
& scanl' nextPosition initialPosition
& filter (== 0)
& length
& print
parseIndividualClicks :: String -> [Int]
parseIndividualClicks (c:cs) =
replicate (read cs) $
case c of
'L' -> -1
'R' -> 1
_ -> 0
parseIndividualClicks _ = []
nextPosition :: Int -> Int -> Int
nextPosition position delta =
(position + delta) `mod` dialUpperBound
trim :: String -> String
trim = dropWhileEnd isSpace . dropWhile isSpaceprivate const val DIAL_UPPER_BOUND = 100
private const val INITIAL_POSITION = 50
fun main() {
(
object {}.javaClass
.getResource("/day1_part1.txt")
?.readText()
?: error("Resource not found")
)
.lineSequence()
.map(String::trim)
.filter(String::isNotEmpty)
.flatMap(::parseClicks)
.scan(INITIAL_POSITION, ::nextPosition)
.count { it == 0 }
.let(::println)
}
fun parseClicks(text: String): Sequence<Int> {
val direction =
when (text.first()) {
'L' -> -1
'R' -> 1
else -> 0
}
val amount = text.drop(1).toInt()
return generateSequence { direction }.take(amount)
}
fun nextPosition(position: Int, delta: Int): Int =
(position + delta).mod(DIAL_UPPER_BOUND)use std::iter::repeat;
use std::ops::Not;
pub const INPUT: &str = r#"
R22
R26
L20
R20
---
L12
L35
R50
"#;
const DIAL_UPPER_BOUND: i32 = 100;
const INITIAL_POSITION: i32 = 50;
fn main() {
let password = INPUT
.lines()
.map(str::trim)
.filter(|line| line.is_empty().not())
.flat_map(parse_move_deltas)
.scan(INITIAL_POSITION, |position, delta| {
*position = (*position + delta).rem_euclid(DIAL_UPPER_BOUND);
Some(*position)
})
.filter(|position| *position == 0)
.count();
println!("{password}");
}
fn parse_move_deltas(text: &str) -> impl Iterator<Item = i32> {
let (direction_text, amount_text) = text.split_at(1);
let amount = amount_text.parse().unwrap_or(0);
let direction = match direction_text {
"L" => -1,
"R" => 1,
_ => 0,
};
repeat(direction).take(amount)
}const input = "
R22
L2
R13
L49
...
L7
L12
L35
R50
"
const dial_upper_bound = 100
const dial_initial_position = 50
pub fn main() {
input
|> string.split("\n")
|> list.map(string.trim)
|> list.filter(fn(line) { !string.is_empty(line) })
|> calculate_password
|> int.to_string
|> io.println
}
fn calculate_password(input: List(String)) -> Int {
input
|> list.flat_map(parse_clicks)
|> list.scan(dial_initial_position, next_position)
|> list.count(fn(pos) { pos == 0 })
}
fn next_position(position, delta) -> Int {
let new_pos = position + delta
new_pos % dial_upper_bound
}
fn parse_clicks(line: String) -> List(Int) {
let direction = case string.first(line) {
Ok("L") -> -1
Ok("R") -> 1
_ -> 0
}
let amount = string.drop_start(line, 1) |> int.parse |> result.unwrap(0)
list.repeat(direction, amount)
}fun main() {
input.splitToSequence(",")
.map { rawRange -> rawRange.split("-") }
.map { (startInclusive, endInclusive) ->
startInclusive.toLong()..endInclusive.toLong()
}
.flatMap { it.asSequence() }
.filter(::isInvalidId)
.sum()
.let(::println)
}
fun isInvalidId(id: Long): Boolean {
val id = id.toString()
val halfLength = id.length / 2
return id.take(halfLength) == id.drop(halfLength)
}fun main() {
input.splitToSequence(",")
.map { rawRange -> rawRange.split("-") }
.map { (startInclusive, endInclusive) ->
startInclusive.toLong()..endInclusive.toLong()
}
.flatMap { it.asSequence() }
.filter(::isInvalidId)
.sum()
.let(::println)
}
fun isInvalidId(id: Long): Boolean {
val id = id.toString()
return id in (id + id).drop(1).dropLast(1)
}fun main() {
input.lineSequence()
.sumOf(::maximumTwoDigitValue)
.let(::println)
}
fun maximumTwoDigitValue(bank: String): Int {
val numbers = bank.map { it.digitToInt() }
val firstMax = numbers.dropLast(1).max()
val indexOfFirstMax = numbers.indexOf(firstMax)
val secondMax = numbers.drop(indexOfFirstMax + 1).max()
return firstMax * 10 + secondMax
}