{ }codelper
같음 비교와 형 변환빈 값(null)P0084

느슨한 같음, 엄격한 같음

값 두 개의 짝이 n개 주어진다.
각 값은 JavaScript 코드에 그대로 쓸 수 있는 글자 토막이다: 정수(예: 5, -12, -0), 큰따옴표로 감싼 문자열(예: "5", "", "abc"), 또는 true, false, null, undefined, NaN 중 하나.
토막을 그 JavaScript 값으로 바꾼 두 값 a, b에 대해 a === b가 참이면 "===", 그렇지 않고 a == b가 참이면 "==", 둘 다 거짓이면 "!="를 한 줄에 하나씩 출력하라.

입력
첫 줄에 n(1 ≤ n ≤ 1000), 다음 n줄에 토막 두 개가 빈칸 하나로 띄워져 있다.
정수는 -1000 이상 1000 이하이고 0 말고는 0으로 시작하지 않는다(-0은 나올 수 있다).
문자열의 따옴표 안은 비어 있거나, 숫자 1~4개만이거나(0으로 시작할 수 있다), 영어 소문자 1~5개만이다.
따옴표 안에 빈칸은 없다.
출력
n줄.
줄마다 ===, ==, != 중 하나
예시 1 · stdin
5
5 "5"
"5" "5"
NaN NaN
null undefined
false "0"
stdout
==
===
!=
==
==
예시 2 · stdin
4
null 0
0 -0
"" 0
true "abc"
stdout
!=
===
==
!=
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 2개 언어 풀이

이 문제는 JavaScript와 TypeScript만 받아요.
타입을 바꿔 가며 비교하는 ==는 이 두 언어의 규칙이에요(Python·Java·C#의 ==는 다른 타입을 이렇게 바꾸지 않아요).
먼저 토막을 값으로 바꿔야 해요: 읽은 그대로 두면 모두 문자열이라 5와 "5"가 같은 문자열이 아니고, NaN과 NaN은 같은 문자열이 돼요.
==는 수와 문자열을 만나면 문자열을 수로("" == 0, "007" == 7), 참거짓을 만나면 참거짓을 1·0으로 바꿔요(false == "0"은 참, true == "abc"는 거짓).
그래서 '참 같은 값끼리 같다'와는 달라요.
하지만 null과 undefined는 서로끼리만 ==이고 null == 0, null == false는 거짓이라, '둘 다 수로 바꿔 비교한다'고 외우면 틀려요(Number(null)은 0이에요).
NaN은 ===로도 ==로도 자기와 같지 않아요.
Object.is는 ===와 비슷하지만 NaN끼리는 같고 0과 -0은 달라서 여기서 쓰면 틀려요.
TypeScript는 string과 number로 좁혀진 두 값을 ==로 비교하면 TS2367 오류를 내서, 여러 타입을 합친 타입(string | number | boolean | null | undefined)으로 받아야 해요.
실행 결과는 JavaScript와 똑같아요.
크레이콘에는 이런 ==가 없어요(빈값으로 계산하면 멈춰요).

JavaScriptmain.js · 20 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]); // 글자 토막 하나를 JavaScript 값으로 바꾼다function parse(token) {  if (token.startsWith('"')) return token.slice(1, -1); // "5" → 문자열 5  if (token === "true") return true;  if (token === "false") return false;  if (token === "null") return null;  if (token === "undefined") return undefined;  if (token === "NaN") return NaN;  return Number(token); // -0 도 그대로 -0} const out = [];for (let i = 1; i <= n; i++) {  const [a, b] = lines[i].trim().split(" ").map(parse);  out.push(a === b ? "===" : a == b ? "==" : "!=");}console.log(out.join("\n"));
TypeScriptmain.ts · 28 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]); type Value = string | number | boolean | null | undefined; // 글자 토막 하나를 값으로 바꾼다function parse(token: string): Value {  if (token.startsWith('"')) return token.slice(1, -1);  if (token === "true") return true;  if (token === "false") return false;  if (token === "null") return null;  if (token === "undefined") return undefined;  if (token === "NaN") return NaN;  return Number(token);} // 타입이 Value(합집합)라서 TS도 == 를 허락한다. string과 number로 좁혀진 두 값이면 TS2367 오류function looselyEqual(a: Value, b: Value): boolean {  return a == b;} const out: string[] = [];for (let i = 1; i <= n; i++) {  const [a, b] = lines[i].trim().split(" ").map(parse);  out.push(a === b ? "===" : looselyEqual(a, b) ? "==" : "!=");}console.log(out.join("\n"));