HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

標準入力から数値列を読み込んで、逆順に標準出力に吐き出す

手元にある各言語で、標準入力から数値列を読み込んで、逆順にしたうえで標準出力に吐き出すプログラムを書いてみようと思ったメモ。

標準入力から入力される数値列の要件は以下の通り。

  • 1行に1つの数値が書かれている
    • 不正入力のチェックは不要とする
  • いくつの数値が入力されるかは不明(ただし、メモリがあふれることが無い程度に手加減する)
  • 入力される数値は符号付32ビット整数とする

入力される数値の上限数設定が無いことで、前々回、前回のように配列を静的に準備しておくということができないので、真面目に動的な配列あるいはリスト構造を考えないといけなくなるところがポイント。

環境

手元にあるものということで、環境は以下のものに限定する。

入力ファイルの例

  • 001.txt
0
1
-1
256
-256
32768
-32768
2147483647
-2147483648

期待される出力の例

  • 001.txt
-2147483648
2147483647
-32768
32768
-256
256
-1
1
0

Java

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.reverse(list);
            for (Integer num : list) {
                out.println(num);
            }
        }
    }
}

Javaの場合、Listの要素を逆順にするメソッドがCollectionsクラスに用意されているので、それを使えば一発。

C

#include <stdio.h>
#include <stdlib.h>

struct _IntNode {
    int value;
    struct _IntNode* prev;
    struct _IntNode* next;
};
typedef struct _IntNode IntNode;
typedef struct {
    int size;
    IntNode* first;
    IntNode* last;
} IntList;

IntList* IntList_new() {
    IntList* list = (IntList*)calloc(sizeof(IntList), 1);
    list->first = NULL;
    list->last = NULL;
    list->size = 0;
    return list;
}
void IntList_destroy(IntList* list) {
    IntNode* node = list->first;
    while (node != NULL) {
        IntNode* next = node->next;
        free(node);
        node = next;
    }
    free(list);
}
void IntList_add(IntList* list, int value) {
    IntNode* node = (IntNode*)calloc(sizeof(IntNode), 1);
    node->next = NULL;
    if (list->last != NULL) {
        list->last->next = node;
        node->prev = list->last;
    } else {
        list->first = node;
        node->prev = NULL;
    }
    list->size++;
    list->last = node;
    node->value = value;
}
void IntList_reverse(IntList* list) {
    int left = 0;
    int right = list->size - 1;
    IntNode* leftNode = list->first;
    IntNode* rightNode = list->last;
    while (left < right) {
        int tmp = leftNode->value;
        leftNode->value = rightNode->value;
        rightNode->value = tmp;

        ++left;
        --right;
        leftNode = leftNode->next;
        rightNode = rightNode->prev;
    }
}

int main(int argc, char** argv) {
    IntList* list = IntList_new();

    int num;
    while (scanf("%ld", &num) == 1) {
        IntList_add(list, num);
    }
    IntList_reverse(list);
    for (IntNode* node = list->first; node != NULL; node = node->next) {
        printf("%d\n", node->value);
    }

    IntList_destroy(list);

    return 0;
}

C言語にはリスト構造がそもそも無いので、そこの実装から。今回はlinked listで実装したが、Javaで言うところのArrayList方式の実装も考えられる。今回は面倒だったので止めたが。

逆順にする処理は、実装したlinked listに対して愚直に各要素の値を入れ替える処理。

C++

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

void reverse_vector(vector<int>& list) {
    for (int left = 0, right = list.size() - 1; left < right; ++left, --right) {
        int tmp = list[left];
        list[left] = list[right];
        list[right] = tmp;
    }
}

int main(int argc, char** argv) {
    vector<int> list;
    int num;

    while (cin >> num) {
        list.push_back(num);
    }

    reverse_vector(list);

    for (int i = 0; i < list.size(); ++i) {
        cout << list[i] << endl;
    }

    return EXIT_SUCCESS;
}

逆順にする処理は、愚直に各要素の値を入れ替える処理。

PHP

<?php

$lines = file('php://stdin');
$ary = array();
foreach ($lines as $line) {
    $ary[] = (int)$line;
}

$left = 0;
$right = count($ary) - 1;
while ($left < $right) {
    $tmp = $ary[$left];
    $ary[$left] = $ary[$right];
    $ary[$right] = $tmp;

    ++$left;
    --$right;
}

foreach ($ary as $num) {
    printf("%d\n", $num);
}

逆順にする処理は、愚直に各要素の値を入れ替える処理。

Python 2

import sys

list = []
while True:
    line = sys.stdin.readline()
    if line == '':
        break
    list.append(int(line))

list.reverse()

for num in list:
    print num

逆順にする処理は、reverseメソッドで一発。

Python 3

import sys

list = []
while True:
    line = sys.stdin.readline()
    if line == '':
        break
    list.append(int(line))

list.reverse()

for num in list:
    print(num)

逆順にする処理は、reverseメソッドで一発。

Ruby

list = []
while line = STDIN.gets
    num = line.to_i
    list.push(num)
end

list = list.reverse()

for num in list
    print num,"\n"
end

逆順にする処理は、reverseメソッドで一発。

Perl

my $line;
my @list = ();
my $count = 0;
while ($line = readline(STDIN)) {
    my $num = $line + 0;
    $list[$count] = $num;
    ++$count;
}

@list = reverse @list;

for (my $i = 0; $i < $count; ++$i) {
    print "$list[$i]\n";
}

逆順にする処理は、reverse関数で一発。

Go

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "strconv"
    "container/list"
)

func main() {
    l := list.New()
    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)
        }
        l.PushBack(num)
        buf = make([]byte, 0, 1024)
    }

    l2 := list.New()
    for elem := l.Back(); elem != nil; elem = elem.Prev() {
        l2.PushBack(elem.Value)
    }
    l = l2

    for elem := l.Front(); elem != nil; elem = elem.Next() {
        fmt.Println(elem.Value)
    }
}

初めてlistコンテナを使ってみた。

逆順にする処理は、元のリストを末尾から捜査して別のリストに放り込むことで実現。 そもそも、入力処理の際にlist.PushFront()すればいいという話もあるが、それはそれとして(ぉ。

bash

#! /bin/bash

nl -ba | sort -nr | cut -f 2

nlコマンドで行番号を付けて、行番号で逆順ソートして、行番号をカットする、という単純な処理。