LeetCode 3754. Concatenate Non-Zero Digits and Multiply by Sum I

문제 https://leetcode.com/problems/concatenate-non-zero-digits-and-multiply-by-sum-i 풀이 문제에서 주어진 조건에 따라서 스트링을 조작하면 되는 간단한 문제이다. 인티저에서 스트링으로, 스트링에서 인티저로 타입 컨버전만 조심하면된다. 주어진 정수 n을 스트링으로 변환한 다음, 앞에서부터 순회하여 "0"을 제거한 스트링 filtered를 만든다. filered를 인티저로 타입 컨버전 해서 x를 구한다. filered의 각 원소를 인티저로 컨버전 한 다음, 합을 구해서 sum을 구한다. x * sum을 리턴한다. 코드 class Solution: def sumAndMultiply(self, n: int) -> int: filtered = "".join(char for char in str(n) if char != "0") if not filtered: return 0 return int(filtered) * sum(map(int, filtered))

July 7, 2026

LeetCode 1288. Remove Covered Intervals

문제 https://leetcode.com/problems/remove-covered-intervals 풀이 여러 개의 구간이 주어지고, 다른 구간에 완전히 포함되는 구간을 제거한 이후, 남은 구간의 개수를 리턴하면 되는 문제이다. 가장 쉬운 방법은 브루트 포스이다. 구간의 개수가 최대 1000개이기 때문에, O(n^2) 방식을 사용해도 충분히 통과 가능하다. 하지만 정렬을 이용하면 쉽게 O(n * log(n)) 으로 풀 수 있다. 구간 시작 부분을 기준으로 오름차순 정렬한다. 시작 부분이 같은 경우엔 끝 부분을 기준으로 내림차순 정렬한다. 정렬된 배열을 앞에서부터 순회하며, 지금까지 등장한 끝 부분의 최대값(maxEnd)을 추적한다. 현재 구간의 끝이 maxEnd보다 크면, 이전 어떤 구간에도 포함되지 않는 새로운 구간이므로 카운트하고 maxEnd를 갱신한다. 현재 구간의 끝이 maxEnd보다 작거나 같으면, 이전 구간에 완전히 포함되는 구간이므로 제거한다. 1번에서 시작 부분 기준으로 정렬했기 때문에, 시작 조건은 자동으로 만족되어 끝 부분만 비교하면 충분하다. ...

July 6, 2026

LeetCode 1301. Number of Paths with Max Score

문제 https://leetcode.com/problems/number-of-paths-with-max-score 풀이 2차원 그리드의 우하단에서 시작해 좌상단까지 이동하면서, 경로에 있는 숫자들의 합의 최대값과 그 최대값이 나오는 경로의 개수를 구하는 문제이다. 최단 거리를 찾는 문제가 아니므로 BFS나 Dijkstra는 필요 없고, 어떻게 경로의 수를 구할지가 핵심이다. 이동 방향은 문제에서 주어져 있으므로, 각 노드에서 인접한 노드들의 값을 활용해 특정 합(v)에 도달하는 경로의 개수를 구할 수 있다. 이런 문제를 효율적으로 푸는 방법은 결국 DP이다. 처음에 점화식을 이렇게 만들었다. dp[r][c][v]: row = r, column = c인 노드에서 지나온 경로에 있는 칸들의 합이 v가 되는 경로의 개수. 테스트 케이스는 통과할 수 있었지만, 실제 제출했을 때는 시간 초과가 되어서 통과하지 못했다. v 차원 때문에 dp공간이 너무 커지는 것이 문제였다. ...

July 5, 2026

TIL. Jul 2, 2026

요약 오늘은 0-1 BFS를 문제에 적용해 보면서 알고리즘 선택의 중요성을 느꼈다. 또한 티스토리 블로그를 Hugo로 이전하기 위한 마이그레이션 스크립트를 작성하며 HTML을 Markdown으로 변환했다. 배운 것 0-1 BFS LeetCode 3286. Find a Safe Walk Through a Grid 사용 언어: Python, Swift 사용 알고리즘: Dijkstra, 0-1 BFS 그동안은 거리 개념이 나오면 무조건 다익스트라를 사용했는데, 처음으로 0-1 BFS를 이용해서 문제를 풀었다. 같은 문제를 Python에서는 다익스트라로 풀었고. 0-1 BFS는 Swift로 풀었다. 기존에 Swift에서 BFS를 사용할 때는 배열과 인덱스 포인터를 이용한 유사 Queue를 사용했는데, 이 방식으로는 큐의 헤드에 원소를 push하는 메소드를 구현하기 어려워서 배열을 사용했다. 문제의 제약조건이 널널해서 배열로 충분히 통과했는데, 어떻게 해야할지는 고민해봐야 할 것 같다. Linked List를 이용해서 큐를 만들면 되지만, 이게 힙와 다익스트라를 쓰는 것보다 코드를 작성하는 입장에서 효율적일지는 잘 모르겠다. ...

July 2, 2026

dev-data-server-light. 4. File Storage

DB 모듈을 마무리하고, 다음으로 구현한 것은 File Storage 모듈이다. DB 모듈과 크게 다르지 않을 것이라고 생각했다. 우선 CRUD 비슷한 메소드를 처리하고, 구조는 DB 모듈에서 충분히 다듬었기 때문이다. 하지만 실제로는 DB보다 인터페이스를 어떻게 정의할 것인지에 대한 고민이 더 많았다. 인터페이스 만들기 처음 작성한 프롬프트는 다음과 같다. Create the initial FileStorage contract in src/storage. Requirements: - Define a FileStorage interface. - The interface is responsible only for storing and retrieving binary file contents. - It should not manage file metadata, ids, ownership, permissions, or database records. - Use Buffer for file contents. - Include only the minimal operations required for file storage: - save(path: string, content: Buffer): Promise<void> - read(path: string): Promise<Buffer> - delete(path: string): Promise<void> - exists(path: string): Promise<boolean> - Add minimal domain errors if necessary. For this step, create only the contract and related types. Do not implement any storage implementation yet. 로컬 파일 시스템을 의식하고 있어서 의심 없이 path라는 이름을 사용했는데, 이 때문에 인터페이스가 구현체를 닮아버리게 되었다. path는 과연 인터페이스를 대표할 수 있는 네이밍인가? ...

July 2, 2026

dev-data-server-light. 3. Database Implementation

DB 모듈의 인터페이스와 서비스 레이어를 만들었으므로, 실제 구현체를 만들어야 한다. 우선 인 메모리(In-Memory)로 가볍게 구현체를 만들었다. 인 메모리 데이터 저장소 인 메모리 방식을 선택한 이유는 첫째로 처음부터 SQL이나 JSON 파일 기반 저장소를 이용해서 구현체를 만드는 것 보다는, 가장 단순한 구현체를 만들어서 DB 기능을 검증하고 빠르게 다음 기능을 만들기 위해서이다. 외부 의존성도 없고, 설정도 필요 없고, 테스트도 쉽다. 구현하기 RecordStore 인터페이스를 다시 보면 다음과 같다. export interface RecordStore { list(collection: string): Promise<StoredRecord[]>; get(collection: string, id: string): Promise<StoredRecord | undefined>; create(collection: string, data: RecordData): Promise<StoredRecord>; replace(collection: string, id: string, data: RecordData): Promise<void>; delete(collection: string, id: string): Promise<boolean>; } 구현체는 이 계약을 그대로 만족하면 된다. 중요한 것은 구현체는 Express를 몰라야하고 순수하게 TypeScript 코드로 짜여야 한다. HTTP 요청이나 라우팅 같은 것은 Router가 책임져야 한다. ...

July 2, 2026

dev-data-server-light. 2. Database CRUD

시스템 모듈을 만든 이후에, 아마도 가장 많이 쓰게 될 DB 모듈을 만들었다. 당시에는 구조도 시스템 모듈과 동일하다고 생각했다. Router가 DB 인터페이스에 의존하고, 이를 구현한 구현체를 주입받는 방식으로 DIP와 DI를 동시에 적용했다. 이 과정 중에서 naming bias 해결하기 id 생성 책임 위치 기존 아키텍처의 문제점 -> 서비스 레이어 도입해서 해결하기 에 대한 고민을 했다. 아래는 고민과 해결 과정이다. CRUD부터 만들기 Mock Server라도 최소한 CRUD는 제공해야 한다. 처음부터 구현체를 만들 필요는 없으므로, 라우터와 인터페이스까지만 만들도록 프롬프트를 작성했다. ...

June 30, 2026

Archive. System Programming 정리 노트

학부연구원 시절 FPGA랑 임베디드 살짝 하면서 적어놨던 노트를 최근 클라우드 정리할 때 발견해서, 간단하게 블로그에 포스팅함. RTOS RTOS(Real-Time Operating System)는 정해진 시간 안에 작업을 수행하는 것을 보장하도록 설계된 운영체제이다. 일반적인 운영체제와 다르게 RTOS는 작업이 정해진 시간 내에 반드시 수행되는 예측 가능성을 가장 중요하게 생각한다. 산업용 장비, 자동차, 드론, 의료기기와 같은 임베디드 시스템에서 주로 사용된다. UART UART(Universal Asynchronous Receiver/Transmitter)는 가장 널리 사용되는 직렬 통신 방식 중 하나이다. 구조가 단순하고 구현이 쉬워 디버깅 콘솔, 센서, 마이크로컨트롤러 간 통신 등에 자주 사용된다. 다만 송신과 수신 장치가 동일한 통신 속도(Baud Rate)를 사용해야 한다. ...

June 29, 2026

dev-data-server-light. 1. System

프로젝트에서 제일 간단한 기능과 구조를 가지기 때문에 가장 먼저 System 모듈을 만들었다. System 모듈의 기능 System 모듈이 제공하는 기능은 단 두 가지뿐이다. GET /system/status GET /system/uptime status는 서버가 정상적으로 동작하는지 알려주고, uptime은 서버가 실행된 이후 얼마나 시간이 지났는지를 반환한다. 비즈니스 로직도 없고, 데이터베이스도 필요하지 않으며, 파일 시스템도 다루지 않기 때문에 구조를 검증하는데 가장 좋다고 판단했다. 구조 검증 System 모듈을 만들면서 확인하고 싶었던 것은 기능이 아니라 구조였다. 당시에 생각했던 구조는 다음과 같았다. ...

June 25, 2026

dev-data-server-light. 0. Concept

시작하기 iOS 프로젝트를 진행하다 보면 생각보다 자주 간단한 API 서버가 필요해진다. 회원가입 화면을 만들거나, 목록 조회 기능을 붙이거나, 이미지 업로드를 테스트할 때도 서버가 필요하다. 물론 실제 백엔드를 구축할 수도 있고, Supabase나 Firebase 같은 BaaS를 사용할 수도 있다. 하지만 작은 개인 프로젝트나 프로토타입 단계에서는 좋은 설계는 아니라고 생각한다. 특히 처음부터 특정 서비스에 의존하기 시작하면, 정작 내가 만들고 싶은 앱의 기능보다 인프라 설정과 서비스 사용법을 익히는 데 더 많은 시간을 쓰게 된다. 앱 개발을 위한 도구가 필요했는데, 어느 순간 도구를 사용하기 위한 공부를 하고 있는 상황이 되는 것이다. ...

June 24, 2026