{ }codelper
absolute valuefloating-point precisionP0134

Part size tolerance check

A factory measures the length of each part it makes and compares it with the nominal length on the drawing. The first line gives the nominal length N and the tolerance T, separated by a space (in mm). The second line gives the number of parts n, and each of the next n lines gives the measured length of one part, starting with part 1. Every length and the tolerance are written with exactly three digits after the decimal point (for example 25.400, 0.050). The deviation of a part is (measured length - N). A part passes if the size of the deviation (its absolute value) is at most T, and fails if it is greater than T. First print the deviation of each part, one per line. Write the deviation with three decimals, with "+" in front if it is above 0 and "-" if it is below 0; if it is 0, write 0.000 with no sign. On the next line print the number of parts that pass. On the next line print the numbers of the failing parts in increasing order, separated by single spaces, or "none" if there are none. On the last line print the number of the part whose deviation has the largest size (the smaller number on a tie).

Input
0.001 ≤ N ≤ 1000.000, 0.000 ≤ T ≤ 10.000, 1 ≤ n ≤ 1,000, 0.000 ≤ measured length ≤ 2000.000
Output
n lines of deviations, the pass count, the failing part numbers (or "none"), the part with the largest deviation
Example 1 · stdin
25.400 0.050
5
25.412
25.450
25.351
25.400
25.349
stdout
+0.012
+0.050
-0.049
0.000
-0.051
4
5
5
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 · 8 languages

The trap is the part that sits exactly on the limit.
Reading 25.450 and 25.400 as doubles and subtracting gives 0.05000000000000071, which is greater than 0.05, so a part that should pass is rejected.
Decimals such as 0.05 and 25.45 cannot be written exactly in binary, so this happens in all eight languages if you use doubles (Craykon numbers are the same doubles as in JS).
The fix uses the promise that there are always three decimals: read the values as integers in 1/1000 mm by deleting the dot, so "25.450" becomes 25450 (Python int(s.replace(".", "")), JS/TS Number(s.replace(".", "")), Java Integer.parseInt(s.replace(".", "")), C# int.Parse(s.Replace(".", "")), C scanf("%d.%d"), C++ std::stoi, Craykon line.Replace(".", "").ToNumber()).
Absolute value is Python abs, JS/TS Math.abs, Java Math.abs, C# Math.Abs, C abs (<stdlib.h>, for int), C++ std::abs, Craykon Mathf.Abs.
In C the floating-point absolute value is a different function, fabs (<math.h>).
Dropping the absolute value and asking d <= T passes every part shorter than nominal, however short.
Printing a negative deviation has a second trap.
Dividing -50 (= -0.050) by 1000 directly: C, C++, Java, C# and JS (Math.trunc) truncate toward zero, so the quotient is 0 and the sign disappears; Python // rounds down, so the quotient is -1 and the % remainder 950, giving "-1.950" (JS Math.floor also gives -1, but its % gives -50, so it is wrong in yet another way).
So write the sign first, then split the absolute value into quotient and remainder, padding the remainder to three digits with leading zeros.

Pythonmain.py · 30 lines
def milli(s):    # "25.400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다    return int(s.replace(".", ""))  def signed(d):    # 부호를 따로 떼고 절댓값으로 자리를 나눈다(-50 // 1000은 -1이라 그대로 나누면 틀린다)    sign = "+" if d > 0 else "-" if d < 0 else ""    a = abs(d)    return f"{sign}{a // 1000}.{a % 1000:03d}"  nominal, tol = map(milli, input().split())n = int(input())passed = 0failed = []worst = 1worst_dev = -1for k in range(1, n + 1):    d = milli(input().strip()) - nominal    print(signed(d))    if abs(d) <= tol:        passed += 1    else:        failed.append(k)    if abs(d) > worst_dev:  # 같으면 앞 번호를 둔다        worst, worst_dev = k, abs(d)print(passed)print(" ".join(map(str, failed)) if failed else "none")print(worst)
JavaScriptmain.js · 27 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");// "25.400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다const milli = (s) => Number(s.trim().replace(".", ""));const signed = (d) => {  const sign = d > 0 ? "+" : d < 0 ? "-" : "";  const a = Math.abs(d); // 부호를 떼고 자리를 나눈다  return sign + Math.floor(a / 1000) + "." + String(a % 1000).padStart(3, "0");};const [nominal, tol] = lines[0].trim().split(/\s+/).map(milli);const n = Number(lines[1]);const out = [];let passed = 0;const failed = [];let worst = 1;let worstDev = -1;for (let k = 1; k <= n; k++) {  const d = milli(lines[1 + k]) - nominal;  out.push(signed(d));  if (Math.abs(d) <= tol) passed++;  else failed.push(k);  if (Math.abs(d) > worstDev) {    worst = k; // 같으면 앞 번호를 둔다    worstDev = Math.abs(d);  }}out.push(String(passed), failed.length ? failed.join(" ") : "none", String(worst));console.log(out.join("\n"));
TypeScriptmain.ts · 28 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");// "25.400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다const milli = (s: string): number => Number(s.trim().replace(".", ""));const signed = (d: number): string => {  const sign = d > 0 ? "+" : d < 0 ? "-" : "";  const a = Math.abs(d); // 부호를 떼고 자리를 나눈다  return sign + Math.floor(a / 1000) + "." + String(a % 1000).padStart(3, "0");};const [nominal, tol] = lines[0].trim().split(/\s+/).map(milli);const n = Number(lines[1]);const out: string[] = [];let passed = 0;const failed: number[] = [];let worst = 1;let worstDev = -1;for (let k = 1; k <= n; k++) {  const d = milli(lines[1 + k]) - nominal;  out.push(signed(d));  if (Math.abs(d) <= tol) passed++;  else failed.push(k);  if (Math.abs(d) > worstDev) {    worst = k; // 같으면 앞 번호를 둔다    worstDev = Math.abs(d);  }}out.push(String(passed), failed.length ? failed.join(" ") : "none", String(worst));console.log(out.join("\n"));
JavaMain.java · 39 lines
import java.io.BufferedReader;import java.io.InputStreamReader; public class Main {    // "25.400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다    static int milli(String s) {        return Integer.parseInt(s.trim().replace(".", ""));    }     static String signed(int d) {        String sign = d > 0 ? "+" : d < 0 ? "-" : "";        int a = Math.abs(d); // 부호를 떼고 자리를 나눈다        return sign + a / 1000 + "." + String.format("%03d", a % 1000);    }     public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        String[] first = in.readLine().trim().split("\\s+");        int nominal = milli(first[0]), tol = milli(first[1]);        int n = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        StringBuilder failed = new StringBuilder();        int passed = 0, worst = 1, worstDev = -1;        for (int k = 1; k <= n; k++) {            int d = milli(in.readLine()) - nominal;            out.append(signed(d)).append('\n');            if (Math.abs(d) <= tol) passed++;            else failed.append(failed.length() > 0 ? " " : "").append(k);            if (Math.abs(d) > worstDev) { // 같으면 앞 번호를 둔다                worst = k;                worstDev = Math.abs(d);            }        }        out.append(passed).append('\n');        out.append(failed.length() > 0 ? failed.toString() : "none").append('\n');        out.append(worst).append('\n');        System.out.print(out);    }}
C#Main.cs · 42 lines
using System;using System.Collections.Generic;using System.Text; class Program{    // "25.400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다    static int Milli(string s) => int.Parse(s.Trim().Replace(".", ""));     static string Signed(int d)    {        string sign = d > 0 ? "+" : d < 0 ? "-" : "";        int a = Math.Abs(d); // 부호를 떼고 자리를 나눈다        return $"{sign}{a / 1000}.{a % 1000:D3}";    }     static void Main()    {        string[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        int nominal = Milli(first[0]), tol = Milli(first[1]);        int n = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        var failed = new List<int>();        int passed = 0, worst = 1, worstDev = -1;        for (int k = 1; k <= n; k++)        {            int d = Milli(Console.ReadLine()) - nominal;            sb.Append(Signed(d)).Append('\n');            if (Math.Abs(d) <= tol) passed++;            else failed.Add(k);            if (Math.Abs(d) > worstDev) // 같으면 앞 번호를 둔다            {                worst = k;                worstDev = Math.Abs(d);            }        }        sb.Append(passed).Append('\n');        sb.Append(failed.Count > 0 ? string.Join(" ", failed) : "none").Append('\n');        sb.Append(worst).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 37 lines
#include <cstdlib>#include <iomanip>#include <iostream>#include <string>#include <vector> // "25.400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다int milli(const std::string& s) {    auto dot = s.find('.');    return std::stoi(s.substr(0, dot)) * 1000 + std::stoi(s.substr(dot + 1));} int main() {    std::string a, b;    int n;    std::cin >> a >> b >> n;    int nominal = milli(a), tol = milli(b);    std::vector<int> failed;    int passed = 0, worst = 1, worstDev = -1;    for (int k = 1; k <= n; k++) {        std::string s;        std::cin >> s;        int d = milli(s) - nominal;        int dev = std::abs(d); // 부호를 떼고 자리를 나눈다        std::cout << (d > 0 ? "+" : d < 0 ? "-" : "") << dev / 1000 << '.' << std::setw(3) << std::setfill('0') << dev % 1000 << '\n';        if (dev <= tol) passed++;        else failed.push_back(k);        if (dev > worstDev) { // 같으면 앞 번호를 둔다            worst = k;            worstDev = dev;        }    }    std::cout << passed << '\n';    if (failed.empty()) std::cout << "none";    for (size_t i = 0; i < failed.size(); i++) std::cout << (i ? " " : "") << failed[i];    std::cout << '\n' << worst << '\n';}
Cmain.c · 35 lines
#include <stdio.h>#include <stdlib.h> /* "25.400"을 정수 25와 400으로 따로 읽는다 — 소수는 언제나 세 자리라 400은 1/1000 단위다 */int read_milli(void) {    int whole, frac;    scanf("%d.%d", &whole, &frac);    return whole * 1000 + frac;} int main(void) {    int nominal = read_milli();    int tol = read_milli();    int n;    scanf("%d", &n);    static int failed[1000];    int nfailed = 0, passed = 0, worst = 1, worst_dev = -1;    for (int k = 1; k <= n; k++) {        int d = read_milli() - nominal;        int a = abs(d); /* 정수 절댓값(실수라면 fabs) */        /* 부호를 따로 쓰고 절댓값으로 자리를 나눈다 */        printf("%s%d.%03d\n", d > 0 ? "+" : d < 0 ? "-" : "", a / 1000, a % 1000);        if (a <= tol) passed++;        else failed[nfailed++] = k;        if (a > worst_dev) { /* 같으면 앞 번호를 둔다 */            worst = k;            worst_dev = a;        }    }    printf("%d\n", passed);    if (nfailed == 0) printf("none");    for (int i = 0; i < nfailed; i++) printf(i ? " %d" : "%d", failed[i]);    printf("\n%d\n", worst);    return 0;}
Craykonmain.cray · 57 lines
천분(줄){    // "25.400" → "25400" → 25400 (소수점 아래는 언제나 세 자리): 실수로 바꾸지 않아 오차가 없다    return 줄.Trim().Replace(".", "").ToNumber();} 부호붙이기(d){    부호 = "";    if (d > 0)    {        부호 = "+";    }    else if (d < 0)    {        부호 = "-";    }    a = Mathf.Abs(d); // 부호를 떼고 자리를 나눈다    return 부호 + Mathf.Quot(a, 1000) + "." + ("" + a % 1000).PadLeft(3, "0");} first = Console.ReadLine().Split();nominal = 천분(first[0]);tol = 천분(first[1]);n = Console.ReadLine().ToNumber();passed = 0;failed = [];worst = 1;worstDev = -1;for (k = 1; k <= n; k++){    d = 천분(Console.ReadLine()) - nominal;    Console.WriteLine(부호붙이기(d));    if (Mathf.Abs(d) <= tol)    {        passed += 1;    }    else    {        failed.Add(k);    }    if (Mathf.Abs(d) > worstDev)    {        worst = k; // 같으면 앞 번호를 둔다        worstDev = Mathf.Abs(d);    }}Console.WriteLine(passed);if (failed.Count > 0){    Console.WriteLine(failed);}else{    Console.WriteLine("none");}Console.WriteLine(worst);