Learn JavaScript

Lesson 7 of 8 · First Programs: The Console, let and const, Types, typeof

Module 1 · First Programs: The Console, let and const, Types, typeof

Problems: First Programs

FreeProblems

In this lesson

  • Read a problem as its parts: the story, Input, Output, Constraints and one sample.
  • Write a program on the starter whose output matches the expected output exactly.
  • Test the edges the constraints allow, such as n = 1, all negative values and an empty input, before you submit.

This page is ten problems, each graded by a judge. The judge runs your program on hidden tests and compares what it prints with what it should print. Seven of them you met as exercises in this module's lessons, or close to them. Three are new.

Problems 1, 3 and 4 (four-operations, sum-of-n and largest-of-n) are free for everyone. The other seven are Pro problems. Locks per problem arrive in a later release, and until then all ten are open, as this whole module is.

Every one starts from the starter of lesson 05, and none needs more than the few lines of for, while and if you saw there. Bob will submit after the sample passes. Zara will run the empty input and the smallest n first, and in this set her habit is worth the marks.

How the judge reads your program

For each hidden test, the judge does four things. It runs your file as node main.js on Node 22, the same as the Playground. It feeds the test's input to standard input, exactly as the stdin box does. It collects what your program printed to standard output. Then it compares that with the expected output.

How the judge grades one hidden test: your output against the expected output One hidden test, start to verdict test input expected output your program node main.js, Node 22 compare line by line stdout Accepted or Wrong Answer Ignored: spaces at the end of a line, line breaks at the very end. Everything else counts.

The comparison ignores spaces at the end of a line and line breaks at the very end of the output, and nothing else. A capital letter where a small one was expected is a wrong answer. So is a missing space after a colon, or a prompt like Enter n: that the Output section never asked for. So a program that prints the right numbers in the wrong shape scores the same as one that prints nothing.

The judge reads standard output only. Anything your program writes to standard error, such as an error message, is not part of the answer. So you can use it for notes to yourself while you test.

The starter, and the lines you write

Every problem's code box opens with the starter lines of lesson 05 and its // your code comment. Then come a comment or two on what this problem needs, then the last line. You write between the comments and the last line, and you change nothing else.

One problem here, reverse-line, reads a whole line with spaces in it. Its starter is the lines variant from lesson 05, and its statement says so. Every other problem reads tokens with next() and nextInt().

The shape of every solution here

const input = ...;   the six starter lines, unchanged
...
const out = [];

// your code: ...
const n = nextInt();          read what Input describes, in order
...                           work out the answer
out.push(answer);             push each output line, in order

console.log(out.join("\n"));  the last line, unchanged
  • Read the values in the order the Input section lists them, with nextInt() for numbers and next() for words.
  • Push exactly the lines the Output section asks for, in that order, and nothing more.
  • Never print a prompt or a label the Output section does not show.

Four checks before you submit

  1. Run the sample. Paste it into the stdin box. If it fails, nothing else matters yet.
  2. Run the edges the constraints allow. n = 1, every value negative, two equal values, and the empty input where the statement allows it.
  3. Read your output beside the expected output. Count the spaces, check every capital letter and every decimal digit.
  4. Check each read. A number read with next() is a string, and the sample may not show it.

So testing is how you find out that a program is finished, not a chore after it.

The hint ladder

Every problem carries three steps you open in order. Hint 1 says what to notice. Hint 2 gives the approach in words. Solution explains the method in two paragraphs, and the reference program sits under it.

Opening a step costs nothing and is recorded, not punished. After the solution, still type the program yourself, because reading it is not the skill. So climb the ladder one rung at a time, and try again between rungs.

Example 1: a whole problem, solved

The problem: read a price and a quantity, and print the cost. Input is one line with two whole numbers; output is one line with one number.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
const price = nextInt();
const quantity = nextInt();
out.push(price * quantity);

console.log(out.join("\n"));
1350

That output is for the input 450 3. Notice what is not in the program: no "Enter the price" prompt, no "Cost:" label, nothing the Output section did not ask for.

Run in Compiler
Example 2: a word and a number in one line of output

Half the problems here print a line that mixes fixed text with values. + joins a string and a value into one string, as lesson 05's banner did.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
const name = next();
const age = nextInt();
out.push(name + " is " + age + " years old.");
out.push("Next year: " + (age + 1));

console.log(out.join("\n"));
Zara is 14 years old.
Next year: 15

That output is for the input Zara 14. The spaces live inside the quotes, because + adds none of its own. The brackets around age + 1 matter, and Common mistakes shows why.

Run in Compiler
Example 3: until the input ends, with a decision

Maria counts the words longer than three letters. This is lesson 05's while shape with lesson 04's if inside it.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
let count = 0;
let word = next();
while (word !== undefined) {
  if (word.length > 3) {
    count = count + 1;
  }
  word = next();
}
out.push(count);

console.log(out.join("\n"));
3

That output is for the input the quick brown fox jumps. quick, brown and jumps have more than three letters. For an empty input the loop never runs, and the program prints 0, which is the right answer here.

Run in Compiler

Where this is used

  • Codeforces and AtCoder. Both contest sites accept JavaScript on Node.js, and both judge a program the way this page does: standard input in, standard output compared. AtCoder's own sample answer in JavaScript reads all of the input with one readFileSync call, as the starter does.
  • LeetCode. It also takes JavaScript, but it calls a function you write and compares what it returns, with no standard input at all. The thinking is the same; only the reading changes.
  • Continuous integration. On every change, a team's test suite runs their program on fixed inputs and compares the results with expected ones. It is a judge for the team's own code.

Common mistakes

1. A prompt the Output section never asked for.

out.push("Enter two numbers:");
out.push(a + b);

The judge answers Wrong Answer on every test, the sample included. Nobody is typing; the input is already there. You will add the prompt because programs in books greet their user. Delete it.

2. Text and a sum with no brackets.

out.push("exact: " + a + b === c);

No message. For 0.1 0.2 0.3 it prints false, without the label. + runs first, left to right, so the line becomes "exact: 0.10.2" === c, which is a string compared with a number. Put brackets around the part that must be worked out first: "exact: " + (a + b === c).

3. Comparing numbers read with next().

const x = next();
const y = next();
out.push(x > y);

No message. For 9 10 it prints true. Two strings are compared letter by letter, like words in a dictionary, and "9" comes after "1". Read numbers with nextInt(), and 9 > 10 is false as it should be.

4. A running value that starts at 0.

let largest = 0;

No message, and the sample may pass. When every value is below zero, nothing beats the 0 you invented, and the program prints 0. Start from the first value the input gives you. Zara's all-negative test exists for exactly this.

Brain teaser

Bob wants his two numbers on one line, separated by a space. He reads the input 3 4 and writes one push.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
const a = nextInt();
const b = nextInt();
out.push(a, b);

console.log(out.join("\n"));

What does it print, and what single change gives Bob his one line?

How many items are in out after that push? Then reread what out.join("\n") puts between items.

Problem 1: four-operationsEasyFree

Kenji's calculator app is broken, and his homework asks four things about every pair of numbers. Read a and b and print their sum, difference, product and quotient.

Input. One line with two whole numbers, a and b.

Output. Four lines: a + b, a - b, a * b and a / b, each as out.join writes it.

Constraints. -1000000 <= a, b <= 1000000, and b is never 0.

Sample. Input 7 2 gives 9, 5, 14 and 3.5 on four lines.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read a and b, then push a + b, a - b, a * b and a / b, one per line.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Which of the four operators did lesson 01 say behaves differently in JavaScript than in C? What does it print for 7 and 2?

Hint 2

Read both numbers with nextInt(), then push the four expressions, one push each, in the order the Output section lists them.

Solution

Two reads and four pushes: out.push(a + b), then a - b, a * b and a / b. There is nothing to format, because out.join turns each number into text with all its digits, as String does. So 3.5 prints as 3.5, 5 / 1 prints as 5, and 1 / 3 prints all of its digits, as the statement asks.

The traps are in the reading, not the sums. With next() instead of nextInt(), a + b joins two strings and 7 2 gives 72. A C habit of Math.floor(a / b) drops the fraction the statement wants. The hidden tests include a negative a, a quotient with many digits, and 0 with a negative b. There the product and the quotient are -0, a negative zero. out.join writes it as 0, while console.log(0 / -5) on its own prints -0: one more reason every answer goes through out.

Problem 2: greetingEasyPro

Zara's library app greets every reader by name when they sign in. Read one name and print the greeting.

Input. One name, a single word with no spaces: letters of any language, digits, a hyphen or an apostrophe.

Output. One line: Hello, , the name, then !.

Constraints. The name is 1 to 100 characters long.

Sample. Input Maria gives Hello, Maria!.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read the name with next(), then push the greeting line.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Where exactly do the spaces go in Hello, Maria!? Count them: one after the comma, none before the !.

Hint 2

Read the name with next(), because it is a word. Build the line with +: the fixed text, the name, the fixed text.

Problem 3: sum-of-nEasyFree

Kenji's food stall records every sale of the day in taka, and a refund as a negative number. Print the day's total.

Input. n, then n whole numbers, on one line or spread over several.

Output. One line with the sum of the n numbers.

Constraints. 1 <= n <= 100000. Each number is between -1000000 and 1000000.

Sample. Input 4 and 10 -3 25 8 gives 40.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read n, then n numbers with nextInt(). Push their sum.

console.log(out.join("\n"));
Run in Compiler

Hint 1

How many numbers come after n? How many times should your program call nextInt() in total?

Hint 2

Keep a let total = 0. Use the for shape from lesson 05 to add nextInt() to it n times, then push it.

Solution

This is lesson 05's first example. Read n and start a total at 0. Add nextInt() to it n times, in a for loop that counts i from 0 while i < n, then push the total. Line breaks in the input do not matter, because tokens arrive in order whatever line they were on.

The largest total is 100000 times 1000000, which is 1011. That is far below Number.MAX_SAFE_INTEGER, so a plain number holds it exactly, as lesson 03 promised. A loop that runs to i <= n reads one token too many and turns the sum into NaN.

Problem 4: largest-of-nMediumFree

Zara logs the temperature at a mountain station every hour, in whole degrees, and in winter most readings are below zero. Print the warmest reading of the day.

Input. n, then n whole numbers.

Output. One line with the largest of the n numbers.

Constraints. 1 <= n <= 100000. Each number is between -1000000 and 1000000.

Sample. Input 5 and 3 9 -2 9 4 gives 9.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read n, then n numbers. Push the largest one.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Work out 3 and -5 -2 -9 on paper. What should the second one print? What would a largest value that starts at 0 print?

Hint 2

Read the first value into let largest. Then read the other n - 1 values, and whenever one is greater, put it in largest. Lesson 04's if does the deciding.

Solution

Start with let largest = nextInt();, the first reading itself, not an invented 0. Then loop n - 1 more times: read x, and if (x > largest) set largest = x. After the loop, push largest. largest = Math.max(largest, x) does the same job as the if, if you prefer it.

Starting at 0 passes the sample and fails every test where all readings are negative, because nothing beats a 0 nobody measured. Reading with next() fails differently: strings compare like dictionary words, so "9" beats "10". For n = 1 the loop never runs, and the only reading is the answer.

Problem 5: celsius-to-fahrenheitMediumPro

Maria's cousin reads the weather in Fahrenheit. Read a temperature in Celsius and print it in Fahrenheit, F = C * 9 / 5 + 32, with exactly one digit after the point.

Input. One number C, whole or with one digit after the point.

Output. One line: F as F.toFixed(1) writes it.

Constraints. -273.1 <= C <= 1000.

Sample. Input 37 gives 98.6; input 100 would give 212.0.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read the temperature in Celsius. Push it in Fahrenheit, with one digit after the point.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Does nextInt() read 36.6 correctly, despite its name? And what does console.log(212) print, compared with 212.0?

Hint 2

Read C with nextInt(), work out F with the formula, and push F.toFixed(1), which always writes exactly one digit after the point.

Problem 6: type-of-eachMediumPro

Alice's form reader turns each text field into the value it most likely means. Read five tokens, convert each by the rule below, and print typeof of each value.

The rule, in order: true and false become booleans; null becomes null; undefined becomes undefined; otherwise, if Number(token) is not NaN, the number; otherwise the token stays a string.

Input. One line with five tokens.

Output. Five lines, the typeof of each value in input order.

Constraints. Each token is 1 to 20 characters long, with no spaces. The four words must match exactly, in small letters.

Sample. Input 42 hello false null 3.5 gives number, string, boolean, object and number.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// For each of the five tokens: turn it into a value by the rule in the statement,
// then push typeof that value.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Why is the fourth line of the sample object? Reread lesson 04's "The two answers that surprise". And what should the token NaN become under the rule?

Hint 2

Loop five times. For each token, an if and else if chain picks the value in the rule's order, with Number.isNaN(Number(token)) as the number test. Then push typeof value.

Problem 7: longest-wordMediumPro

Kenji's word game needs the longest word from a list that has no count in front: the words come until the input ends.

Input. Words of the letters a to z and A to Z, separated by spaces and line breaks. There may be no words at all.

Output. The longest word; the first one if several share the greatest length; none if there are no words.

Constraints. Each word is 1 to 20 letters. The input holds at most 200000 characters.

Sample. Input tea biscuit cake gives biscuit.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read words with next() until it gives undefined. Push the longest one,
// the first one if several share the greatest length, or none if there were no words.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Two words of the same length: which one must you keep, and does > or >= keep it? And what is the first next() on an empty input?

Hint 2

Read the first word into let best. Use the while shape to read the rest, replacing best only when a word is strictly longer. After the loop, push none if best is undefined, or best otherwise.

Problem 8: reverse-lineMediumPro

Amara prints every clue of her puzzle backwards. Read one line, spaces and punctuation included, and print it reversed. This starter is the lines variant, so next() hands over the whole line.

Input. One line of text, possibly empty.

Output. The same line with its characters in reverse order.

Constraints. 0 to 1000 characters, each printable ASCII (codes 32 to 126).

Sample. Input Zara runs 5 km gives mk 5 snur araZ.

const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Lines variant: next() returns the next whole line, empty lines included.
// Read the line with next(). Push it written backwards.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Why would the token starter lose this line's spaces? Which character of the line must come out first, and what is its position?

Hint 2

line[i] is the character at position i, counting from 0, and line.length - 1 is the last. Walk i down from there to 0, adding each character to a let reversed = "".

Problem 9: close-enoughHardPro

Zara does not trust decimals since lesson 03. Read a, b and c, and print whether a + b is exactly c, and whether it is within 1e-9 of c.

Input. One line with three numbers, each with at most six digits after the point.

Output. Two lines: exact: and the result of a + b === c, then close: and the result of Math.abs(a + b - c) < 1e-9.

Constraints. Each number is between -1000 and 1000.

Sample. Input 0.1 0.2 0.3 gives exact: false and close: true.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read a, b and c. Push "exact: " and whether a + b === c,
// then "close: " and whether a + b is within 1e-9 of c.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Try out.push("exact: " + a + b === c) on the sample and read what it prints. Which + runs first?

Hint 2

Work out each true-or-false answer inside its own brackets first, then join it to its label with +. For close, use lesson 03's closeness test with a + b in place of the sum.

Problem 10: times-tableHardPro

Maria wants the times table of n on her wall, with the columns lined up. Print ten lines n x i = p. Pad i to 2 characters, and pad p to as many characters as n * 10 has.

Input. One whole number n.

Output. Ten lines, for i from 1 to 10.

Constraints. 1 <= n <= 100000.

Sample. Input 7 gives ten lines, from 7 x 1 = 7 to 7 x 10 = 70.

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out
// Read n. Push ten lines, n x i = p, with i padded to 2 characters
// and p padded to as many characters as n * 10 has.

console.log(out.join("\n"));
Run in Compiler

Hint 1

Write the lines for n = 10 by hand. How wide is the widest product, 100, and how wide is the narrowest, 10?

Hint 2

Work out the width once, before the loop: the number of characters in String(n * 10). Then, for i from 1 to 10, build one line from n, i padded to 2 and the product padded to that width, with padStart.

Common doubts

  • My program passes the sample. Why does a hidden test fail?

    The sample is one small case, chosen to explain the statement. The hidden tests add n = 1, all negative values, equal values, an empty input where it is allowed, and the largest input. Run those yourself first, as Zara does.

  • Can I use console.log inside my code instead of out.push?

    For a few lines it usually gives the same output; Problem 1's negative zero is the exception. For many lines it is slow, as lesson 05 measured, and mixing the two can print lines out of order. Push everything to out and the question never comes up.

  • Can I print a debugging line while I test?

    Yes, with console.error(x). It writes to standard error, which the Playground shows and the judge ignores. A debugging line in out is part of your answer, and makes it wrong.

  • Some of these use for, while and if, which Module 4 teaches. Am I meant to know them?

    Only the shapes lessons 04 and 05 showed, used as given. Module 4 explains how they work and what else they can do. Every problem here needs no more than those shapes.

Key takeaways

  • A judge compares your standard output with the expected output, ignoring only trailing spaces and final line breaks.
  • Read values in the order Input lists them: nextInt() for numbers, next() for words.
  • Push exactly the lines Output asks for: no prompts, no labels it does not show.
  • Put brackets around a sum or a comparison before you join it to text.
  • Start a running value from the first input, never from an invented 0.
  • Test the sample, then the edges: n = 1, all negative, ties, the empty input.

Next is the module test: ten questions on this module's lessons. After it, Module 2 opens the question this module kept putting off: what + does when one side is a string.

Module test

Ten questions on this module. Pass at 70%, and you can take it as many times as you like.

Take the module test

End of lesson 7

Get every problem accepted, and the lesson is done.

0 of 3 free problems accepted

Next: Module Test: First Programs

Problems: First Programs | Learn JavaScript | Progsity