手元にある各言語で、標準入力から数値列を読み込んで、降順にソートしたうえで標準出力に吐き出すプログラムを書いてみようと思ったメモ。
プログラム言語にもよるが、昇順は簡単なのに降順となったとたんに苦労するケースがあったりする。
標準入力から入力される数値列の要件は以下の通り。
- 1行に1つの数値が書かれている
- 最大で256個の数値が入力される
- 入力される数値は符号付32ビット整数とする
環境
手元にあるものということで、環境は以下のものに限定する。
入力ファイルの例
0
1
-1
256
-256
32768
-32768
2147483647
-2147483648
期待される出力の例
2147483647
32768
256
1
0
-1
-256
-32768
-2147483648
入力される数値の上限数が分かっているということで、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) {
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
関数の大小による戻り値が逆になっていること。
#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
$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
という、ただそれだけ。
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
を指定していること。
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
を指定していること。
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
昇順との違いは、逆順になるように何か書いているが、正直よく分かってない(待て)。
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
がなにやらややこしいことになっていること。
sort -nr
昇順との違いは、いわずもがな、-r(everse)
の指定。