Java
common-lisp
C#
C言語
python3

プログラミング学習/競技プログラミングサイトについて忘備録・メモ

はじめに

最近は以下のようなプログラミング学習/競技プログラミングサイトが流行ってますね。

というわけで、自分もちょっとだけやってみたので、自分なりに調べたり勉強したことを忘備録・メモしていこうと思います。

標準入力した数値文字列を多次元配列へ格納する処理

以下のように1行の入力をそれぞれ配列に格納する処理。
※ 縦横同じ大きさの多次元配列を想定しています。

123 => arr[0][0]、arr[0][1]、arr[0][2]
456 => arr[1][0]、arr[1][1]、arr[1][2]
789 => arr[2][0]、arr[2][1]、arr[2][2]

これが出来ると後はこの配列を利用して色々出来ると思います。

C言語プログラム

#include <stdio.h>
#include <string.h>

#define MAX_ROW 1000
#define MAX_COL 1000

static int g_map[MAX_ROW][MAX_COL];

int main(int argc, char** argv){
  int count1, count2, len;
  char input_string[MAX_ROW];

  /* 最初の標準入力 */
  scanf("%s", input_string);
  len = strlen(input_string);

  for(count1 = 0; count1 < len; count1++){
    /* 2回目以降はここで標準入力を行う */
    if(count1 > 0){
      scanf("%s", input_string);
    }
    for(count2 = 0; count2 < len; count2++){
      /* ASCII文字の数字から"0"(0x30)を引けば数値が得られます。 */
      g_map[count1][count2] = input_string[count2] - '0';
    }
  }

  /* 表示 */
  for(count1 = 0; count1 < len; count1++){
    for(count2 = 0; count2 < len; count2++){
      printf("%d", g_map[count1][count2]);
    }
    printf("\n");
  }

  return 0;
}

動的配列を使う場合
こっちの方が汎用性が高いかな?

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

#define INPUT_STRING_LEN 1000

int **g_map;

int main(int argc, char** argv){
  int count1, count2, len;
  char input_string[INPUT_STRING_LEN];

  /* 最初の標準入力 */
  scanf("%s", input_string);
  len = strlen(input_string);

  /* 動的配列確保 */
  g_map = malloc(sizeof(int *) * len);
  for (int i = 0; i < len; i++) {
    g_map[i] = malloc(sizeof(int) * len);
  }

  for(count1 = 0; count1 < len; count1++){
    /* 2回目以降はここで標準入力を行う */
    if(count1 > 0){
      scanf("%s", input_string);
    }
    for(count2 = 0; count2 < len; count2++){
      /* ASCII文字の数字から"0"(0x30)を引けば数値が得られます。 */
      g_map[count1][count2] = input_string[count2] - '0';
    }
  }

  /* 表示 */
  for(count1 = 0; count1 < len; count1++){
    for(count2 = 0; count2 < len; count2++){
      printf("%d", g_map[count1][count2]);
    }
    printf("\n");
  }

  /* 開放処理 */
  for (int i = 0; i < len; i++) {
    free(g_map[i]);
  }
  free(g_map);

  return 0;
}

C++プログラム

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main(int argc, char** argv){
    string      input_string;
    const char* c_string;
    int         length, count1, count2;
    vector< vector<int> > arr;

    cin >> input_string;
    length = input_string.size();

    /* resize関数を使って動的にサイズを変更 */
    arr.resize(length);
    for(count1 = 0; count1 < length; count1++){
        arr[count1].resize(length);
    }

    for(count1 = 0; count1 < length; count1++){
        if(count1 > 0){
            cin >> input_string;
        }
        for(count2 = 0; count2 < length; count2++){
            c_string = input_string.c_str();
            arr[count1][count2] = c_string[count2] - '0';
        }
    }

    for(count1 = 0; count1 < length; count1++){
        for(count2 = 0; count2 < length; count2++){
            cout << arr[count1][count2];
        }
        cout << endl;
    }

    // delete処理はデストラクタ内で行ってくれるので不要

    return 0;
}

Python3プログラム

if __name__=="__main__":
    input_string = input()
    length = len(input_string)

    map_data = [[0 for i in range(length)] for j in range(length)]

    for count1 in range(0, length):
        if count1 > 0:
            input_string = input()
        for count2 in range(0, length):
            map_data[count1][count2] = int(input_string[count2])

    # 表示
    for count1 in range(0, length):
        for count2 in range(0, length):
            print(map_data[count1][count2], end='')
        print("")

CommonLispプログラム

(defun main ()
  (let (count1
        count2
        input-string
        str-length
        map-data)
    (setf input-string (read-line))
    (setf str-length (length input-string))
    (setf map-data (make-array `(,str-length ,str-length)))
    (dotimes (count1 str-length)
      (setf count2 0)
      (if (> count1 0)
          (setf input-string (read-line)))
      (loop :for char :across input-string
            :do (setf (aref map-data count1 count2) (digit-char-p char))
                (incf count2)))
    ;; 表示
    (dotimes (count1 str-length)
      (dotimes (count2 str-length)
        (format t "~d" (aref map-data count1 count2)))
      (format t "~%"))))

Javaプログラム

import java.util.*;

class Main{
    /* 定数宣言 */
    public static final int MAX_ROW = 1000;
    public static final int MAX_COL = 1000;

    /* MAIN関数 */
    public static void main(String[]args){
        int question[][] = new int[MAX_ROW][MAX_COL];
        int count1, count2, len;
        String input_string;

        Scanner cin = new Scanner(System.in);

        input_string = cin.nextLine();
        len = input_string.length();

        for(count1 = 0; count1 < len; count1++){
            if(count1 > 0){
                input_string = cin.nextLine();
            }
            for(count2 = 0; count2 < len; count2++){
                question[count1][count2] = input_string.charAt(count2) - '0';
            }
        }

        /* 表示 */
        for(count1 = 0; count1 < len; count1++){
            for(count2 = 0; count2 < len; count2++){
                System.out.print(question[count1][count2]);
            }
            System.out.println("");
        }
    }
}

C#プログラム

using System.IO;
using System;

class Program
{
    /* 定数定義 */
    public const int MAX_ROW = 1000;
    public const int MAX_COL = 1000;

    /* MAIN関数 */
    static void Main()
    {
        int[,] question = new int[MAX_ROW, MAX_COL];
        int count1, count2, len;
        String input_string;

        input_string = Console.ReadLine();
        len = input_string.Length;

        for(count1 = 0; count1 < len; count1++){
            if(count1 > 0){
                input_string = Console.ReadLine();
            }
            for(count2 = 0; count2 < len; count2++){
                question[count1, count2] = input_string[count2] - '0';
            }
        }

        /* 表示 */
        for(count1 = 0; count1 < len; count1++){
            for(count2 = 0; count2 < len; count2++){
                Console.Write(question[count1, count2]);
            }
            Console.WriteLine("");
        }
    }
}

Rubyプログラム

if __FILE__ == $0
    input_string = gets.chomp
    length = input_string.length - 1

    map_data = Array.new

    (0..length).each do |count1|
        if count1 > 0 then
            input_string = gets.chomp
        end
        map_data << input_string.split("").map(&:to_i)
    end

    #表示
    (0..length).each do |count1|
        (0..length).each do |count2|
            print map_data[count1][count2]
        end
        puts ""
    end
end

最後に

ざっと5種類の言語(C言語、Python3、CommonLisp、Java、C#)でのプログラムを書いてみました。(ぶっちゃけ、もっと良い書き方もあると思いますが・・・)
これはアルゴリズムを書く前にデータを用意するための準備段階のプログラムですね。
実際にはここから配列に格納したデータを使って問題解決を行っていきます。
今回は配列でしたが、他にもリスト、キュー、スタック、ハッシュなど色んなデータ構造があるので問題に合わせて選択していけたらいいですね。