링크 https://www.acmicpc.net/problem/1550
문제 16진수 수를 입력받아서 10진수로 출력하는 프로그램을 작성하시오.
입력 첫째 줄에 16진수 수가 주어진다. 이 수의 최대 길이는 6글자이다. 16진수 수는 0~9와 A~F로 이루어져 있고, A~F는 10~15를 뜻한다. 또, 이 수는 음이 아닌 정수이다.
출력 첫째 줄에 입력으로 주어진 16진수 수를 10진수로 변환해 출력한다.

 

Python 3

result = int(input(), 16)
print(result)

 

Kotlin (JVM)

import java.util.Scanner

fun main(args: Array<String>) {
    val sc: Scanner = Scanner(System.`in`)
    val result = sc.nextInt(16)
    println(result)
}
fun main() {
    val input = readLine()
    if (!input.isNullOrEmpty()) {
        val result = input.toInt(16)
    	println(result)
    }
}

 

node.js

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString();
var result = parseInt(input, 16);
console.log(result);
const readline = require("readline");
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
rl.on("line", function(line) {
    input = line.toString(16);
    let result = parseInt(input, 16);
    console.log(result);
}).on("close", function() {
    process.exit();
});

 

 

링크 https://www.acmicpc.net/problem/1271
문제 갑부 최백준 조교는 동전을 최소로 바꾸는데 성공했으나 김재홍 조교가 그 돈을 발견해서 최백준 조교에게 그 돈을 나누자고 따진다.
그 사실이 전 우주로 알려지자 우주에 있던 많은 생명체들이 자신들에게 돈을 분배해 달라고 당장 달려오기 시작했다.
프로토스 중앙 우주 정부의 정책인, ‘모든 지적 생명체는 동등하다’라는 규칙에 입각해서 돈을 똑같이 분배하고자 한다.
한 생명체에게 얼마씩 돈을 줄 수 있는가?
또, 생명체들에게 동일하게 분배한 후 남는 돈은 얼마인가?
입력 첫째 줄에는 최백준 조교가 가진 돈 n과 돈을 받으러 온 생명체의 수 m이 주어진다. (1 ≤ m ≤ n ≤ 10의 1000승, m과 n은 10진수 정수)
출력 첫째 줄에 생명체 하나에게 돌아가는 돈의 양을 출력한다. 그리고 두 번째 줄에는 1원씩 분배할 수 없는 남는 돈을 출력한다.

 

간단한 나눗셈 문제 같지만 사실 숫자 타입을 묻는 문제다. 10의 1000승은 Double을 넘는 범위로, BigInteger로 처리해야 한다. 파이썬은 int()에서 타입을 자동으로 처리하지만 코틀린과 node.js는 그렇지 않다.

 

 

Python 3

input = input().split()
n = int(input[0])
m = int(input[1])
print(n // m)
print(n % m)
n, m = map(int, input().split())
print(n // m)
print(n % m)

 

Kotlin (JVM)

import java.util.Scanner

fun main(args: Array<String>) {
    val sc: Scanner = Scanner(System.`in`)
    val n = sc.nextBigInteger()
    val m = sc.nextBigInteger()
    println(n / m)
    println(n % m)
}
fun main() {
    val input = readLine()?.split(" ")
    if (!input.isNullOrEmpty()) {
        val n = input[0].toBigInteger()
        val m = input[1].toBigInteger()
        println(n / m)
        println(n % m)
    }
}

 

node.js

const fs = require("fs");
const input = fs.readFileSync('/dev/stdin').toString().split(" ");
var n = BigInt(input[0]);
var m = BigInt(input[1]);
var quotient = (n / m).toString();
var remainder = (n % m).toString();
console.log(quotient);
console.log(remainder);
const readline = require("readline");
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
rl.on("line", function(line) {
    input = line.split(" ");
    let n = BigInt(input[0]);
    let m = BigInt(input[1]);
    let quotient = (n / m).toString();
    let remainder = (n % m).toString();
    console.log(quotient);
    console.log(remainder);
}).on("close", function() {
    process.exit();
});

 

 

링크 https://www.acmicpc.net/problem/1001
문제 두 정수 A와 B를 입력받은 다음, A-B를 출력하는 프로그램을 작성하시오.
입력 첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력 첫째 줄에 A-B를 출력한다.

 

Python 3

num = input().split()
a = int(num[0])
b = int(num[1])
print(a - b)
a, b = map(int, input().split())
print(a - b)

 

Kotlin (JVM)

import java.util.Scanner

fun main(args: Array<String>) {
	val sc: Scanner = Scanner(System.`in`)
	val a = sc.nextInt()
	val b = sc.nextInt()
	println(a - b)
}
fun main() {
	val input = readLine()?.split(" ")
	if (!input.isNullOrEmpty()) {
		val a = input[0].toInt()
		val b = input[1].toInt()
		println(a - b)
	}
}

 

node.js

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString().split(" ");
var a = parseInt(input[0]);
var b = parseInt(input[1]);
console.log(a - b);
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on("line", function(line) {
    input = line.split(" ");
	let a = parseInt(input[0]);
	let b = parseInt(input[1]);
	console.log(a - b);
}).on("close", function() {
	process.exit();
});

 

 

링크 https://www.acmicpc.net/problem/1000
문제 두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력 첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력 첫째 줄에 A+B를 출력한다.

 

Python 3

num = input().split()
a = int(num[0])
b = int(num[1])
print(a + b)
a, b = map(int, input().split())
print(a + b)

 

Kotlin (JVM)

import java.util.Scanner

fun main(args: Array<String>) {
    val sc: Scanner = Scanner(System.`in`)
    val a = sc.nextInt()
    val b = sc.nextInt()
    println(a + b)
}
fun main() {
    val input = readLine()?.split(" ")
    if (!input.isNullOrEmpty()) {
        val a = input[0].toInt()
        val b = input[1].toInt()
        println(a + b)
    }
}

 

node.js

const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").toString().split(" ");
var a = parseInt(input[0]);
var b = parseInt(input[1]);
console.log(a + b);
const readline = require("readline");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on("line", function(line) {
    input = line.split(" ");
    let a = parseInt(input[0]);
    let b = parseInt(input[1]);
    console.log(a + b);
}).on("close", function() {
    process.exit();
});

mdn 문서를 읽다가

 

마크업을 구글링하다가

 

마크업 언어 나무위키 페이지에 들어갔다가

 

마크다운 나무위키 페이지에 들어갔다가

 

파이썬의 이스터에그를 찾음

 

재밌는 만화도 찾음

 

굿

 

import antigravity

#웹툰 링크로 이동

import this 

#파이썬의 철학이라고 함

 

 

한참 삽질하면서 왜 안되는지 자가진단 하려고 짠 테스트 코드... 짜 놓고도 원인을 못 찾아서 문제였지만 그래도 comprehension 연습한 셈 치자.

import random

student_number = random.randint(2, 30)
lost_list = sorted(set(random.randint(1, student_number) for x in range(random.randint(1, student_number))))
reserve_list = sorted(set(random.randint(1, student_number) for x in range(random.randint(1, student_number))))

print("n      (%d)" % student_number)
print("lost   (%d) =" % len(lost_list), lost_list)
print("reserve(%d) =" % len(reserve_list), reserve_list)
print(solution(student_number, lost_list, reserve_list))

for 문의 범위 안에 있는 인자를 for 문 안에서 삭제해서 오류가 남. 한참 끙끙대다 if 문에서 reserve 조건을 처리해서 해결하나 싶었는데 학생 수만큼 도느라 lost에 [3, 4]가 있고 reserve에 [4]가 있을 때 3을 처리하면서 reserve의 4를 삭제해버려서 답이 틀리는 경우가 있었다. 그걸 보완해서 바로 제출한 게 아래 코드.

def solution(n, lost, reserve):
    for student in range(1, n + 1):
        if student in lost and student in reserve:
            lost.remove(student)
            reserve.remove(student)
        elif student in lost and student - 1 in reserve:
            lost.remove(student)
            reserve.remove(student - 1)
        elif student in lost and student + 1 in reserve:
            if student + 1 not in lost:
                lost.remove(student)
                reserve.remove(student + 1)
    answer = n - len(lost)

    return answer

그리고 좀더 깔끔하게 하고자 장 씨의 도움을 받은 게 아래 코드.

if를 두 번 쓴 이유는 조건이 위아래가 다르므로 구분하기 위함.

def solution(n, lost, reserve):
    for student in range(1, n + 1):
        if student not in lost:
            continue
        if student in reserve:
            lost.remove(student)
            reserve.remove(student)
        elif student - 1 in reserve:
            lost.remove(student)
            reserve.remove(student - 1)
        elif (student + 1 in reserve) and (student + 1 not in lost):
            lost.remove(student)
            reserve.remove(student + 1)
    answer = n - len(lost)

    return answer

for 문을 학생 수만큼 돌지 않아도 되므로 회전을 최소화하려고 lost로 돌게 만든 코드

마지막 elif 문처럼 여러 문이 중첩되어 있으면 구분하기 쉽게 괄호()를 넣어주는 게 좋다고 한다.

def solution(n, lost, reserve):
    recover_count = 0
    for student in lost:
        if student in reserve:
            recover_count += 1
            reserve.remove(student)
        elif student - 1 in reserve:
            recover_count += 1
            reserve.remove(student - 1)
        elif (student + 1 in reserve) and (student + 1 not in lost):
            recover_count += 1
            reserve.remove(student + 1)
            
    answer = n - (len(lost) + recover_count)
    return answer

집합은 교집합, 합집합, 차집합을 구할 수 있다. 교집합은 집합 사이에 &를 넣어 표기한다. 여기서 lost와 reserve를 교집합을 빼고 집합으로 for 문에 넘겼다. 이러면 .remove를 했을 때 list에서보다 처리가 빠르다.

def solution(n, lost, reserve):
    dupl = set(lost) & set(reserve)
    lost, reserve = set(lost) - dupl, set(reserve) - dupl
    answer = n - len(lost)
    
    for student in lost:
        if student - 1 in reserve:
            reserve.remove(student - 1)
            answer += 1
        elif student + 1 in reserve:
            reserve.remove(student + 1)
            answer += 1

    return answer

그 이유는 리스트에서 뭔가를 찾아서 지운다는 것은 아래처럼 for문으로 리스트 안에 있는 그 값을 찾아서 지우느라 시간이 걸리기 때문이다. 반면 사전형이나 집합은 hash이므로 바로 값을 찾아서 삭제할 수 있다. 그래서 처리 속도가 빨라지는 것이다.

_lost.remove(f)

def remove(f):
    for item in _lost:
        if item == f:
            del _lost[f]
            break

 

python의 time 모듈을 불러와 오늘 날짜와 시간을 구하거나 특정 날짜를 불러올 수도 있다. 

KST는 한국 시간 기준으로 UTC보다 9시간 빠르다.

import time

utc = time.gmtime()     # time.struct_time(tm_year=2020, tm_mon=11, tm_mday=4, tm_hour=11, tm_min=12, tm_sec=23, tm_wday=2, tm_yday=309, tm_isdst=0)
kst = time.localtime()  # time.struct_time(tm_year=2020, tm_mon=11, tm_mday=4, tm_hour=20, tm_min=12, tm_sec=23, tm_wday=2, tm_yday=309, tm_isdst=0)

n1 = time.strftime('%c', utc)       # Wed Nov  4 11:12:23 2020
n2 = time.asctime(utc)              # Wed Nov  4 11:12:23 2020
n3 = time.strftime('%c %z', kst)    # Wed Nov  4 20:12:23 2020 +0900
n4 = time.ctime()                   # Wed Nov  4 20:12:23 2020

날짜와 시간을 다루는 데는 여러 가지 방법이 있는데 이건 파이썬 문서를 참고하자.

백준 코딩 문제를 푸는데 n 줄의 입력을 받을 때 for 문으로 input을 받는 것 말고 다른 방법이 없을까 고민하다가 sys.stdin.readlines() 명령어를 알게 되었다. 이걸 쓰면 사용자가 ^Z(또는 ctrl + z)를 누르기 전까지 입력을 계속할 수 있다. 그런데 파이참에서 실행을 하면 이 키가 먹지 않아서 무한 입력을 해야 하는 상황이 생긴다. 이럴 때는 sys.stdin.readlines() 말고 sys.stdin.readline()을 써서 입력을 원하는 만큼 받을 수 있다. 결국 for문을 써야 하지만 이런 방법도 있다는 것을 알게 되어 좋다. 사실 문제에서는 입력을 받는 게 중요하지 않았지만 그래도 문제를 보면서 여러 가지 상황을 생각해볼 수 있어서 공부하는 데 많은 도움이 되었다.

import sys

def readlines(count):
    result = []
    for i in range(count):
        result.append(*sys.stdin.readline().split())
    return result

print(readlines(3))

그리고 한 줄에 여러 문자를 받아서 각각 넘기고 싶으면 .split()을 사용한다. 괄호 안에 아무것도 쓰지 않으면 공백을 기준으로 값을 나누고, 괄호 안에 문자를 넣으면 그 문자를 기준으로 값을 나눈다.

>>>text = "It's a text, not a code."
>>>result = text.split()
>>>result
["It's", 'a', 'text,', 'not', 'a', 'code.']

>>>result = text.split(",")
>>>result
["It's a text", ' not a code.']

또한 문자 좌우의 공백을 제거하는 메소드도 있다. 오른쪽 공백을 제거하려면 rstrip(), 왼쪽은 lstrip(), 양쪽은 strip()이다.

만약 여러 줄로 값을 받았을 경우 아래와 같이 줄바꿈 문자가 포함된 채로 값을 받는다.

1
2
3
['1\n', '2\n', '3\n']

이 때 sys.stdin.readline().rstrip()이나 sys.stdin.readline().strip()을 사용해서 받으면 공백 문자가 사라진다.

1
2
3
['1', '2', '3']

이걸 만약 ssys.stdin.readline().split()으로 공백을 기준으로 나눠 받으면?

1
2
3
[['1'], ['2'], ['3']]

리스트로 저장되므로 *sys.stdin.readline().split()으로 입력을 풀어서 받아도 되지만 그냥 위의 방법을 쓰는 게 좋다.

 

+덧

 

그리고 input()과 raw_input()이 있다는 걸 알았다. 이전 버전에서는 input()이 raw_input()을 evaluate 한 값이어서 input()의 속도가 느렸고 출력되는 값도 달랐다. 그 때문에 raw_input()이나 sys.stdin 명령어를 쓰는 일이 있었다고 한다. 그런데 내가 쓰는 파이썬 3.7에는 raw_input()이 사라졌고 input()만 있다. input()은 더이상 evaluate를 한 값을 돌려주지 않는다. 이전 버전에서의 raw_input()의 기능을 지금 버전의 input()이 하는 거구나 하고 이해했는데, 맞으려나?

우테코 코딩 테스트를 준비하며 아직 잘 모르는 javascript보다 python으로 온라인 코딩 테스트를 보는 게 낫지 않을까 생각해서 다시 python을 복습하고 있다. 객체 지향에 관해 내가 보고 있는 책(게임으로 배우는 파이썬)에서는 역시나 클래스와 객체의 관계를 붕어빵 틀과 붕어빵으로 설명하고 있다.

 

예전에 이 개념이 잘 이해가 안 가서 인터넷으로 검색해봤는데, 클래스와 객체의 관계는 붕어빵 틀과 붕어빵이 아니라는 글을 보고 이해가 갔다. 그런데 오늘 다시 그 글을 보니 이해가 바로 안 되더라. 그 글에서는 클래스는 붕어빵 틀이 아니라 붕어빵 공장이라고 했다. 객체는 '실체'라는 것을 강조했다. 

 

곰곰이 생각해보니 객체는 실체이며 클래스는 실체가 아니라는 것, 따라서 붕어빵 틀은 실체이므로 그 비유가 잘못되었다는 말이라는 생각이 들었다. 배민 문방구 제품을 예로 들어보자.

 

배민 문방구에는 현재 세 가지 종류의 파일이 있다. 흰 바탕에 검은색 글씨가 프린트 되어 있다는 점은 똑같다. 다른 것은 프린트된 글씨의 내용이다. 여기서 '불투명한 재질'이며 '오른쪽으로 열린다'는 것, 크기는 'A4 사이즈'이고 '흰 바탕'에 '검은색 글씨'가 있다는 것이 배민 문방구 파일에 대한 약속이다. 파일을 만드는 공장에서는 이 약속에 따라 '아- 보람차다'라고 쓰인 파일과, '까먹지 말자'라고 쓰인 파일, '선생님 감사해요'라고 쓰인 파일을 만들었을 것이다. 이 세 가지 파일이 바로 클래스(약속)로 만들어진 객체다. 

 

그러므로 나는 클래스는 붕어빵 틀도 아니며 붕어빵 공장도 아니라고 말하고 싶다. 클래스는 '약속'이다. 이런 이런 조건으로 물건을 만들겠다고 정한 내용이 클래스며 그 정한 내용으로 만든 실체가 객체다.

+ Recent posts