標準入力から数値列を読み込んで、降順にソートして標準出力に吐き出す
手元にある各言語で、標準入力から数値列を読み込んで、降順にソートしたうえで標準出力に吐き出すプログラムを書いてみようと思ったメモ。 プログラム言語にもよるが、昇順は簡単なのに降順となったとたんに苦労するケースがあったりする。
標準入力から入力される数値列の要件は以下の通り。
- 1行に1つの数値が書かれている
- 不正入力のチェックは不要とする
- 最大で256個の数値が入力される
- 入力される数値は符号付32ビット整数とする
環境
手元にあるものということで、環境は以下のものに限定する。
- CentOS 7
入力ファイルの例
- 001.txt
0 1 -1 256 -256 32768 -32768 2147483647 -2147483648
期待される出力の例
- 001.txt
2147483647 32768 256 1 0 -1 -256 -32768 -2147483648
Java
入力される数値の上限数が分かっているということで、Javaでは2パターン作ってみた。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.Arrays; public class Main { public static void main(String[] args) { try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(System.out) ) { String buf; int count = 0; int[] ary = new int[256]; while ((buf = in.readLine()) != null) { ary[count] = Integer.parseInt(buf); ++count; } Arrays.sort(ary, 0, count); // 降順ソートする手段がないので、昇順ソートした後に逆順にする。。 for (int left = 0, right = count - 1; left < right; ++left, --right) { int tmp = ary[left]; ary[left] = ary[right]; ary[right] = tmp; } for (int i = 0; i < count; ++i) { out.println(ary[i]); } } catch (NumberFormatException e) { // 今回は不正入力のチェックは不要なので、RuntimeExceptionを投げておく。 throw new RuntimeException(e); } catch (IOException e) { e.printStackTrace(); } } }
昇順との違いは‥コメントにある通り「降順ソートする手段がないので、昇順ソートした後に逆順にする」という手法を取っていること。
import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner; public class Main { public static void main(String[] args) { try (Scanner in = new Scanner(System.in); PrintWriter out = new PrintWriter(System.out) ) { List<Integer> list = new ArrayList<>(); while (in.hasNextInt()) { list.add(in.nextInt()); } Collections.sort(list, Collections.reverseOrder()); for (Integer num : list) { out.println(num); } } } }
昇順との違いは、Collections.sort
の第2パラメータに逆順を表すComparator
を指定していること。
C
#include <stdio.h> #include <stdlib.h> int cmp(const void* pa, const void* pb) { int a = *(const int*)pa; int b = *(const int*)pb; if (a < b) { return 1; } else if (a > b) { return -1; } else { return 0; } } int main(int argc, char** argv) { int ary[256]; int count = 0; while (scanf("%ld", &ary[count]) == 1) { ++count; } qsort(ary, count, sizeof(int), cmp); for (int i = 0; i < count; ++i) { printf("%d\n", ary[i]); } return 0; }
昇順との違いは、cmp
関数の大小による戻り値が逆になっていること。
C++
#include <algorithm> #include <iostream> #include <vector> using namespace std; bool cmp(int a, int b) { return a > b; } int main(int argc, char** argv) { vector<int> list; int num; int count = 0; while (cin >> num) { list.push_back(num); ++count; } sort(list.begin(), list.end(), cmp); for (int i = 0; i < list.size(); ++i) { cout << list[i] << endl; } return EXIT_SUCCESS; }
昇順との違いは、sort
関数の第3パラメータに比較関数を指定して、逆順になるように関数を定義していること。
PHP
<?php $lines = file('php://stdin'); $ary = array(); foreach ($lines as $line) { $ary[] = (int)$line; } rsort($ary); foreach ($ary as $num) { printf("%d\n", $num); }
昇順がsort
に対して、降順がrsort
という、ただそれだけ。
Python 2
import sys list = [] while True: line = sys.stdin.readline() if line == '': break list.append(int(line)) list.sort(reverse=True) for num in list: print num
昇順との違いは、reverse
パラメータにTrue
を指定していること。
Python 3
import sys list = [] while True: line = sys.stdin.readline() if line == '': break list.append(int(line)) list.sort(reverse=True) for num in list: print(num)
昇順との違いは、reverse
パラメータにTrue
を指定していること。
Ruby
list = [] while line = STDIN.gets num = line.to_i list.push(num) end list = list.sort() {|a, b| b <=> a} for num in list print num,"\n" end
昇順との違いは、逆順になるように何か書いているが、正直よく分かってない(待て)。
Perl
my $line; my @list = (); my $count = 0; while ($line = readline(STDIN)) { my $num = $line + 0; $list[$count] = $num; ++$count; } @list = sort {$b <=> $a} @list; for (my $i = 0; $i < $count; ++$i) { print "$list[$i]\n"; }
昇順との違いは、$a
と$b
が逆になっていること。これで逆順(降順)ソートになるのだから、つくづくPerlは不思議な言語‥
Go
package main import ( "bufio" "fmt" "io" "os" "strconv" "sort" ) func main() { tmp := make([]int, 256) count := 0 stdin := bufio.NewReader(os.Stdin) buf := make([]byte, 0, 1024) for { line, prefix, err := stdin.ReadLine() if err == io.EOF { break } buf = append(buf, line...) if prefix { continue } s := string(buf) num, err2 := strconv.Atoi(s) if err2 != nil { panic(err2) } tmp[count] = num count++ buf = make([]byte, 0, 1024) } ary := make([]int, count) for i := 0; i < count; i++ { ary[i] = tmp[i] } sort.Sort(sort.Reverse(sort.IntSlice(ary))) for i := 0; i < count; i++ { fmt.Println(ary[i]) } }
これが最適なコードなのかどうかよく分からん‥
昇順との違いは、sort.Ints
がなにやらややこしいことになっていること。
bash
#! /bin/bash sort -nr
昇順との違いは、いわずもがな、-r(everse)
の指定。