읽기 전에 알아두면 좋아요
아래 개념이 익숙하면 본문을 바로 읽으세요. 낯선 개념만 링크에서 복습하면 됩니다.
- 문자열 알고리즘 기초: 순회·문자 판별·대소문자 변환·숫자 추출문자열의 각 문자를 순서대로 읽고 위치를 확인하는 방법을 복습합니다. 숫자의 등장 순서를 유지해 자릿수를 누적하고 선행 0을 구분합니다.
- 기초 구현 패턴: 조건·정수 계산·순회·상태 갱신변수에 값을 담고 조건에 따라 합·개수·최솟값을 갱신하는 기초부터 확인합니다. 순회 중 필요한 상태를 정하고 갱신하는 기본 패턴입니다.
개념과 예제는 실행하지 않아도 읽을 수 있습니다. 내 컴퓨터·터미널에서 직접 실행하는 과정은 선택 실습입니다.
과정 위치와 선택 복습 안내
과정 위치: 문자열 응용 · 문제
과정 위치는 이 글이 속한 묶음입니다. 이 단계의 모든 개념을 먼저 읽을 필요는 없습니다. 위에 연결한 개념 중 낯선 내용만 복습하세요. 문제의 조건·상태·갱신 순서는 익숙한 언어로 설명하면 됩니다.
JavaScript로 문법·실행 복습하기 (선택)
개념 글의 코드는 JavaScript 예시입니다. 문제 화면에서는 JavaScript·Python·Java·C++·C# 중 익숙한 언어의 함수를 작성하세요. 본문의 Node.js 입출력 예시는 로컬 실행을 위한 별도 안내입니다.
문자와 숫자가 섞인 문자열에서 숫자만 추출하는 문제의 출력은 무엇인가요?
문자 사이의 숫자를 원래 순서대로 이어 하나의 자연수로 반환하는 문제입니다. 문자열·문자 범위·정수의 기본을 준비하고, 아래 입력·반환 계약을 확인해 직접 풀어보세요.
본문 근거: MDN isNaN 문서 · MDN parseInt 문서 · Node.js fs.readFileSync 문서
문제·입출력·제약
문자와 숫자가 섞인 문자열에서 숫자만 골라, 등장한 순서대로 자연수를 만듭니다. 숫자를 크기순으로 정렬하거나 각 자릿수를 더하는 문제가 아닙니다.
- 입력: 첫 줄에 숫자가 섞인 문자열 하나가 주어집니다.
- 문자열 길이는 50을 넘지 않습니다. 별도의 최소 길이는 명시되어 있지 않습니다.
- 추출해 만든 자연수는 100,000,000 이하입니다.
- 출력: 만들어진 자연수를 한 줄에 출력합니다.
제공 자료의 「섹션 3. 문자열 탐색.pdf」 3쪽과 「3. 숫자만 추출.txt」를 2026년 10월 13일 직접 확인했습니다. TXT는 HTML 안의 함수 실행 예제이며 특정 온라인 채점 플랫폼은 제시하지 않습니다. 이 글은 같은 문제를 PDF의 한 줄 입력 형식에 맞춰 Node.js 표준 입력으로 실행합니다.
원본 예제 입력
g0en2T0s8eSoft
원본 예제 출력
208
원본 설명에 있는 tge0a1h205er도 같은 원리로 1205가 됩니다. 앞의 0은 수의 표기에 남지 않지만, 2와 5 사이의 0은 유지해야 합니다.
목차
예제 문자열에서 숫자에만 밑줄을 그어 보세요. 0, 2, 0, 8이 남습니다.
- 문자 하나가 숫자인지 어떤 범위로 검사하면 될까요?
- 찾은 숫자를 배열 뒤에 넣으면 원래 순서가 유지될까요?
- 문자열
0208과 수208은 출력할 때 무엇이 다를까요?
숫자를 고르는 단계와, 골라 놓은 문자열을 수로 바꾸는 단계를 나누면 풀이가 단순해집니다.
직접 풀어보기
먼저 선택한 언어의 입력·반환 계약에 맞춰 작성해 보세요. 힌트 받기와 정답과 비교하기는 코드를 실행하지 않는 AI 분석입니다. 해답·해설은 아래에서 필요할 때 펼칠 수 있습니다.
AI 힌트
코드를 실행한 채점 결과가 아닌 AI의 코드 분석입니다.
해답·해설 보기
function solve(input) {
const text = input.split(/\r?\n/, 1)[0];
let result = 0;
for (const character of text) {
if (character >= '0' && character <= '9') {
result = result * 10 + Number(character);
}
}
return String(result);
}
첫 줄의 숫자를 원래 순서대로 이어 만든 100,000,000 이하 자연수를 십진 문자열로 반환합니다. 자연수를 만들 수 있는 입력이 비교 대상입니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다.
def solve(input):
text = input.split('\n', 1)[0].removesuffix('\r')
result = 0
for character in text:
if '0' <= character <= '9':
result = result * 10 + int(character)
return str(result)
첫 줄의 숫자를 원래 순서대로 이어 만든 100,000,000 이하 자연수를 십진 문자열로 반환합니다. 자연수를 만들 수 있는 입력이 비교 대상입니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다.
class Solution {
public String solve(String input) {
String text = input.split("\\r?\\n", 2)[0];
int result = 0;
for (int i = 0; i < text.length(); i++) {
char character = text.charAt(i);
if (character >= '0' && character <= '9') {
result = result * 10 + (character - '0');
}
}
return String.valueOf(result);
}
}
첫 줄의 숫자를 원래 순서대로 이어 만든 100,000,000 이하 자연수를 십진 문자열로 반환합니다. 자연수를 만들 수 있는 입력이 비교 대상입니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. new Solution().solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다.
#include <sstream>
#include <string>
std::string solve(const std::string& input) {
std::istringstream in(input);
std::string text;
std::getline(in, text);
if (!text.empty() && text.back() == '\r') text.pop_back();
int result = 0;
for (char character : text) {
if (character >= '0' && character <= '9') {
result = result * 10 + (character - '0');
}
}
return std::to_string(result);
}
첫 줄의 숫자를 원래 순서대로 이어 만든 100,000,000 이하 자연수를 십진 문자열로 반환합니다. 자연수를 만들 수 있는 입력이 비교 대상입니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다.
public class Solution {
public string Solve(string input) {
string text = input.Split('\n')[0].TrimEnd('\r');
int result = 0;
foreach (char character in text) {
if (character >= '0' && character <= '9') {
result = result * 10 + (character - '0');
}
}
return result.ToString();
}
}
첫 줄의 숫자를 원래 순서대로 이어 만든 100,000,000 이하 자연수를 십진 문자열로 반환합니다. 자연수를 만들 수 있는 입력이 비교 대상입니다. 입력 예시 전체를 문자열 input으로 전달하고 출력 문자열을 반환합니다. new Solution().Solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. LF·CRLF·끝 줄바꿈 없음에 같은 결과를 반환합니다.
접근 과정
1. 각 문자가 0~9인지 확인합니다
for...of로 문자열을 왼쪽부터 읽습니다. 현재 문자 character가 '0' 이상이고 '9' 이하일 때만 숫자 배열에 넣습니다. 여기서는 숫자 문자의 범위를 명시적으로 비교하므로 영문 대소문자는 따로 바꾸지 않아도 됩니다.
2. 순서를 유지한 채 모은 뒤 십진수로 바꿉니다
digits.push(character)는 발견한 숫자를 배열 끝에 넣습니다. 모든 문자를 확인한 뒤 join('')으로 구분자 없이 연결하고, parseInt(..., 10)으로 십진 정수를 만듭니다. 맨 앞의 0은 수로 변환하면서 자연스럽게 사라집니다. 모든 0을 지우는 처리를 하면 중간·끝 자릿수가 달라지므로 안 됩니다.
원본 접근에서 유지한 점과 보완한 점
원본 TXT 역시 문자열을 순회하며 숫자 문자를 모은 뒤 parseInt로 변환합니다. 이 두 단계는 유지했습니다. 다만 원본의 !isNaN(x)는 숫자 문자인지를 직접 검사하는 함수가 아니라 수로 변환했을 때 NaN인지 검사합니다. 공백도 수로 바꾸면 0이어서 통과할 수 있으므로, 최종 풀이에서는 0~9 범위를 명시했습니다. 이는 문자와 숫자로 된 원본 예제를 고치는 것이 아니라 검사 의도를 더 분명하게 만든 보완입니다.
또한 반복 중 문자열을 계속 이어 붙이는 대신 배열에 모아 마지막에 한 번 연결하고, 변환할 진법 10을 명시했습니다. 배열 이름은 digits로 두어 저장하는 값이 숫자 문자임을 드러냈습니다.
해설과 정답의 근거
반복문의 매 단계에서 배열에는 지금까지 읽은 부분의 숫자만, 읽은 순서대로 들어 있습니다. 숫자가 아닌 문자는 건너뛰므로 이 성질은 바뀌지 않고, 숫자는 뒤에 추가하므로 기존 숫자들의 순서도 바뀌지 않습니다.
문자열 끝까지 읽으면 배열은 전체 문자열에서 추출해야 할 숫자들의 목록이 됩니다. 이를 빈 구분자로 연결하면 원하는 자릿수 문자열이 되고, 십진수로 변환하면 선행 0을 제외한 자연수가 됩니다. 그래서 정렬이나 숫자 합산은 필요하지 않습니다.
다음 전체 코드를 solution.cjs에 저장하세요. 예제 입력을 input.txt에 넣고 node solution.cjs < input.txt를 실행하면 208이 출력됩니다. 외부 패키지는 필요하지 않습니다.
const fs = require('node:fs');
const input = fs.readFileSync(0, 'utf8');
const text = input.split(/\r?\n/, 1)[0];
function solution(text) {
const digits = [];
for (const character of text) {
if (character >= '0' && character <= '9') {
digits.push(character);
}
}
return parseInt(digits.join(''), 10);
}
console.log(solution(text));
첫 줄은 /\r?\n/으로 구분합니다. LF와 CRLF를 모두 처리하며 마지막 줄바꿈이 없어도 입력이 유지됩니다. 공백으로 나누지 않으므로 첫 줄의 문자를 온전히 검사합니다.
예제 추적
g는 숫자가 아니므로 건너뛰고 첫0을 배열에 넣습니다.e,n을 지나2를 넣으면 숫자 목록은 0, 2입니다.T다음의0,s다음의8을 차례로 넣습니다.- 남은
eSoft를 건너뛰면 연결된 문자열은0208입니다. - 십진 정수로 바꾼 최종 출력은
208입니다.
경계값과 시간·공간 복잡도
다음은 원본 예제와 구별하여 따로 만든 검사입니다.
1→1: 한 자리 자연수를 확인합니다.a0001b→1: 선행 0이 여러 개일 때를 확인합니다.a1b0c0→100: 끝의 0을 지우지 않는지 확인합니다.a9b8c7→987: 숫자를 정렬하지 않고 원래 순서를 지키는지 확인합니다.a100000000z→100000000: 허용된 최대 결과를 확인합니다.- 문자 a 41개 뒤에
100000000을 붙인 길이 50의 입력과, 0 49개 뒤에 1을 붙인 길이 50의 입력도 검사했습니다. - 표지의
a3b0x7z→307은 설명용으로 만든 예시이며 원본 수록 예제가 아닙니다.
2026년 10월 13일 Node.js v24.19.0에서 원본 입출력 예제 1개, 원본 설명 예시 1개, 별도로 만든 입력 14개를 각각 LF·CRLF·끝 줄바꿈 없음으로 실행했습니다. 총 48회 실행이 예상 결과와 일치했습니다. 이 중 공백이 있는 a1 b2의 결과 12는 방어적 동작 확인이며, 숫자가 없는 abc의 NaN은 자연수를 만들 수 없는 범위 밖 입력의 동작으로 따로 구분했습니다. 원문이 이런 입력의 정답을 정의한다고 주장하지 않습니다.
- 시간 복잡도: O(n). 길이 n의 문자열을 한 번 순회하고, 모은 숫자를 연결·변환하는 데도 최대 O(n)이 듭니다. 배열 끝 추가는 분할 상환 O(1)로 봅니다.
- 공간 복잡도: O(n). 입력 문자열과 숫자 배열, 연결한 숫자 문자열을 저장합니다.
최대 길이는 50이고 만들어지는 수는 100,000,000 이하이므로 이 방식으로 충분합니다. 숫자가 없는 입력의 처리 정책이나 매우 큰 정수를 다루는 범용 추출기로 범위를 넓히지는 않습니다.
자가 확인
- 모든 0을 없애면
a1b0c0의 답이 어떻게 잘못될까요? - 숫자를 크기순으로 정렬하면 원본의 어떤 조건을 어기나요?
- 변형 문제로 결과를 자연수가 아닌 숫자 문자열로 요구한다면, 선행 0을 보존하려고 마지막 단계를 어떻게 바꿀까요?
확인 기준 보기
0이 자릿값에 미치는 영향과 등장 순서 보존을 설명할 수 있으면 됩니다. 변형 문제에서는 정수 변환을 생략하고 연결한 문자열을 반환합니다. 이는 원본과 다른 출력 조건입니다.
문자열에서 특정 문자만 남기는 발상을 복습하려면 유효한 팰린드롬 풀이를 참고하세요. 원본 자료의 다음 문제는 “가장 짧은 문자거리”입니다.
기술 동작은 MDN isNaN 문서, MDN parseInt 문서, Node.js fs.readFileSync 문서를 2026년 10월 13일 확인했습니다. 문제 조건·예제의 기준은 위에서 밝힌 사용자 제공 TXT와 PDF입니다.
글 소개·학습 준비·전체 목차
숫자만 추출하려면 문자열을 왼쪽부터 읽으며 0~9에 해당하는 문자만 모은 뒤, 십진수로 바꾸면 됩니다. “문자 사이에 흩어진 숫자를 어떻게 순서대로 이어 붙일까요?”라는 질문을 풀어 봅니다. 문자열·배열·조건문·반복문·함수의 기본 문법을 알고 있다면, 앞의 0은 없애고 중간과 끝의 0은 유지하는 JavaScript 풀이를 완성할 수 있습니다.

이 글이 도움이 되었나요?
이어서 공부하기
체크포인트: 해설을 가리고 다시 풀고, 경계 입력을 하나 바꾸어 예상 결과와 실제 결과를 비교하세요. 전처리할 문자와 비교할 문자를 구분하고 마지막 문자·마지막 묶음을 확인하세요.
다음 추천 · 알고리즘 개념: 양방향 스캔: 왼쪽·오른쪽 상태로 가장 가까운 문자 찾기
권장 순서는 학습 가이드와 같습니다. 다른 순서는 접힌 참고 목록에서 확인할 수 있습니다. 읽음 표시는 숙달이나 채점 결과가 아닙니다.
원래 과정 목록 순서 (선택)
읽음 기록
읽음 — / 전체 57개 · 필수 57개
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.