{ }codelper
equality and coercionnull valuesP0084

Loose or strict equality

You are given n pairs of values.
Each value is a token you could write directly in JavaScript code: an integer (for example 5, -12, -0), a string in double quotes (for example "5", "", "abc"), or one of true, false, null, undefined, NaN.
Turn both tokens into those JavaScript values a and b, and print one line per pair: "===" if a === b is true, otherwise "==" if a == b is true, and "!=" if both are false.

Input
First line n (1 ≤ n ≤ 1000), then n lines with two tokens separated by one space.
Integers are between -1000 and 1000 and have no leading zeros except 0 itself (-0 may appear).
Inside the quotes a string is empty, or only 1 to 4 digits (a leading 0 is allowed), or only 1 to 5 lowercase letters.
There are no spaces inside quotes.
Output
n lines, each one of ===, ==, !=
Example 1 · stdin
5
5 "5"
"5" "5"
NaN NaN
null undefined
false "0"
stdout
==
===
!=
==
==
Example 2 · stdin
4
null 0
0 -0
"" 0
true "abc"
stdout
!=
===
==
!=
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 2 languages

This problem takes JavaScript and TypeScript only.
A == that converts types before comparing is a rule of these two languages (== in Python, Java or C# does not convert other types like this).
First turn the tokens into values: left as read, everything is a string, so 5 and "5" are different text and NaN and NaN are the same text.
When == meets a number and a string it turns the string into a number ("" == 0, "007" == 7), and a boolean becomes 1 or 0 (false == "0" is true, true == "abc" is false), so it is not the same as 'both truthy or both falsy'.
But null and undefined are == only to each other, and null == 0 and null == false are false, so 'both sides become numbers' is wrong (Number(null) is 0).
NaN is not equal to itself with either === or ==.
Object.is looks like === but treats NaN as equal to itself and 0 and -0 as different, so it gives wrong answers here.
TypeScript rejects == between values narrowed to string and number (error TS2367), so take them as a union type (string | number | boolean | null | undefined); at run time it behaves exactly like JavaScript.
Craykon has no == like this (calculating with null stops the program).

JavaScriptmain.js · 20 lines
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 lines
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"));