{ }codelper
等価比較と型変換null 値P0084

ゆるい等価、厳密な等価

二つの値の組が n 個与えられる。
各値は JavaScript のコードにそのまま書ける文字の断片である:整数(例:5、-12、-0)、二重引用符で囲んだ文字列(例:"5"、""、"abc")、または true、false、null、undefined、NaN のいずれか。
断片をその JavaScript の値に変えた二つの値 a、b について、a === b が真なら "==="、そうでなく a == b が真なら "=="、どちらも偽なら "!=" を一行に一つずつ出力せよ。

入力
1 行目に 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()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 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 とまったく同じです。
Craykon にはこのような == はありません(なし で計算すると止まります)。

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"));