マージソート(mergeSort)9種類の言語で書いてみた

何故書くか?は前前前前回書いたので、以下、即本題。 今回は、C言語によるアルゴリズム事典を参考にしたので、C言語は省くことにした。

実行環境はcoding groundというWEB上でコンパイルから実行までしてくれるサービスを使用。

本当は定義したメソッドだけ書いておきたいのだけど、後々動作確認したいと思った時にコピペで済むので前処理等も書いておいた。

JavaScript

function margeSort(arr, head, tail) {
    let m = (head, tail) => {
        if (head < tail) {
            let mid = Math.floor((head + tail) / 2);
            m(head, mid);
            m(mid+1, tail);

            let l = arr.slice(head, mid+1);
            let r = arr.slice(mid+1, tail+1);
            let i = head;
            while (l.length > 0 && r.length > 0) {
                if (l[0] <= r[0]) {
                    arr[i++] = l.shift();
                } else {
                    arr[i++] = r.shift();
                }
            }
            while (l.length > 0) {
                arr[i++] = l.shift();
            }
        }
        return arr;
    }
    m(0, arr.length-1);
    return arr;
}
console.log(margeSort([148, 651, 124, 638, 567, 435, 185, 413, 35]));

PHP

function margeSort(&$arr) {
    function m (&$arr, $head, $tail) {
        if ($head < $tail) {
            $mid = floor(($head + $tail) / 2);
            m($arr, $head, $mid);
            m($arr, $mid+1, $tail);

            $l = array_slice($arr, $head, $mid+1 - $head);
            $r = array_slice($arr, $mid+1, ($tail - $mid));
            $i = $head;
            while (count($l) > 0 && count($r) > 0) {
                if ($l[0] <= $r[0]) {
                    $arr[$i++] = array_shift($l);
                } else {
                    $arr[$i++] = array_shift($r);
                }
            }
            while (count($l) > 0) {
                $arr[$i++] = array_shift($l);
            }
        }
        return $arr;
    }
    return m($arr, 0, count($arr)-1);
}

$arr = array(651, 148 , 124, 638, 567, 435, 185, 413, 841, 35);
print_r(margeSort($arr));

Perl

use POSIX qw(floor);

my @arr = (148, 651, 124, 638, 567, 435, 185, 413, 841, 35);
print join(",", &margeSort(@arr));

sub margeSort {
    my ($arr) = @_;
    my $m;
    $m = sub {
        my ($arr, $head, $tail) = @_;
        if ($head < $tail) {
            my $mid = floor(($head + $tail) / 2);
            $m->(\@arr, $head, $mid);
            $m->(\@arr, $mid + 1, $tail);

            my @l = @arr[$head .. ($mid+1)];
            my @r = @arr[($mid+1) .. ($tail+1)];
            my $i = $head;
            while ($#l > 0 && $#r > 0) {
                if ($l[0] <= $r[0]) {
                    @arr[$i++] = shift(@l);
                } else {
                    @arr[$i++] = shift(@r);
                }
            }
            while ($#l > 0) {
                @arr[$i++] = shift(@l);
            }
        }
        return @arr;
    };
    return $m->(\@arr, 0, $#arr, $m);
}

Python

import math
def margeSort(arr):
    def m(head, tail):
        if head < tail:
            mid = math.floor((head + tail) / 2)
            m(head, mid)
            m(mid + 1, tail)

            l = arr[head: mid + 1]
            r = arr[mid+1: tail+1]
            k = head
            while len(l) > 0 and len(r) > 0:
                if l[0] <= r[0]:
                    arr[k] = l.pop(0)
                else:
                    arr[k] = r.pop(0)
                k += 1

            while len(l) > 0:
                arr[k] = l.pop(0)
                k += 1
        return arr
    return m(0, len(arr)-1)

arr = [104, 865, 413, 541, 304, 354, 165, 150]
print(margeSort(arr))

Ruby

def margeSort(arr)
    # 内部メソッドだが、スコープはトップレベル
    def m(arr, head, tail) 
        if head < tail
            mid = ((head + tail) / 2).floor
            m(arr, head, mid)
            m(arr, mid + 1, tail)

            l = arr.slice(Range.new(head, mid + 1, true))
            r = arr.slice(Range.new(mid + 1, tail + 1, true))
            i = head
            while l.size > 0 && r.size > 0 do
                if l[0] <= r[0]
                    arr[i] = l.shift
                else
                    arr[i] = r.shift
                end
                i += 1
            end

            while l.size > 0 do
                arr[i] = l.shift
                i += 1
            end
        end
        return arr
    end
    return m(arr, 0, arr.size-1)
end

arr = [148, 651, 124, 638, 567, 435, 185, 413, 841, 35]
print margeSort(arr)

Go

package main

import (
    "fmt"
    "math"
)

func main() {
    arr := []int{148, 651, 124, 638, 567, 435, 185, 413, 841, 35};
    fmt.Println(margeSort(arr));
}
func margeSort(arr []int) []int {
    var m func(int, int) []int;
    m = func(head int, tail int) []int {
        if head < tail {
            mid := int(math.Floor(float64(head + tail) / 2));
            m(head, mid);
            m(mid + 1, tail);

            l := make([]int, len(arr[head:mid+1]), (cap(arr[head:mid+1])+1))
            r := make([]int, len(arr[mid+1:tail+1]), (cap(arr[mid+1:tail+1])+1))
            copy(l, arr[head:mid+1]);
            copy(r, arr[mid+1:tail+1]);

            i := head;
            for len(l) > 0 && len(r) > 0 {
                if l[0] <= r[0] {
                    arr[i] = l[0];
                    l = l[1:];
                } else {
                    arr[i] = r[0];
                    r = r[1:];
                }
                i++;
            }

            for len(l) > 0 {
                arr[i] = l[0];
                l = l[1:];
                i++;
            }
        }
        return arr;
    }
    return m(0, len(arr)-1);
}

Kotlin

fun main(args: Array<String>) {
    var arr = arrayOf(148, 651, 124, 638, 567, 435, 185, 413, 841, 35);
    var result = margeSort(arr);
    for(i in result) println(i)
}

fun margeSort(arr: Array<Int>): Array<Int> {
    return m(arr, 0, arr.size-1);
}

fun m(arr: Array<Int>, head: Int, tail: Int): Array<Int> {
    if (head < tail) {
        var mid = Math.floor((head + tail).toDouble() / 2).toInt();
        m(arr, head, mid);
        m(arr, mid + 1, tail);

        var l = arr.sliceArray(head..(mid));
        var i = 0;
        var j = mid + 1;
        var k = head;
        while (i < l.size && j <= tail) {
            if (l[i] <= arr[j]) {
                arr[k++] = l[i++];
            } else {
                arr[k++] = arr[j++];
            }
        }

        while (i < l.size){
            arr[k++] = l[i++];
        }
    }
    return arr;
}

Swift

import Foundation
import Glibc

func margeSort(a: [Int]) -> [Int] {
    var arr = a
    func m(head: Int, tail: Int) {
        if head < tail {
            let mid = Int(floor(Double(head + tail) / 2))
            m(head: head, tail: mid)
            m(head: mid + 1, tail: tail)

            var l = arr[head...mid] // インデックスは0番からではなく、headの値からとなる
            var i = head
            var j = mid + 1
            var k = head
            while i <= mid && j <= tail {
                if l[i] <= arr[j] {
                    arr[k] = l[i]
                    i += 1
                } else {
                    arr[k] = arr[j]
                    j += 1
                }
                k += 1
            }

            while i <= mid {
                arr[k] = l[i]
                i += 1
                k += 1
            }
        }
    }
    m(head: 0, tail: arr.count-1)
    return arr
}
print(margeSort(a: [867, 104, 413, 541, 304, 354, 165, 150]))

C#

using System.IO;
using System;

class Program
{
    static void Main()
    {
        int[] arr = {148, 651, 124, 638, 567, 435, 185, 413, 841, 35};
        Console.WriteLine(string.Join(", ", margeSort(arr)));
    }

    static int[] margeSort(int[] arr) {
        Func<int, int, int[]> m = null;
        m = (head, tail) => {
            if (head < tail) {
                int mid = (int)Math.Floor((double)(head + tail) / 2);
                m(head, mid);
                m(mid + 1, tail);

                int[] l = new int[mid+1-head];
                Array.Copy(arr, head, l, 0, mid+1-head);
                int i = 0;
                int j = mid + 1;
                int k = head;
                while (i < l.Length && j <= tail) {
                    if (l[i] <= arr[j]) {
                        arr[k++] = l[i++];
                    } else {
                        arr[k++] = arr[j++];
                    }
                }

                while (i < l.Length) {
                    arr[k++] = l[i++];
                }
            }
            return arr;
        };
        m(0, arr.Length-1);
        return arr;
    }
}