Kawaii Lab

プログラミングとかサービス開発とか

CodilityのLesson2をGoで解いてみた(続き)

概要

オンラインコーディングの試験であるCodilityのLesson2を自分なりに解いてみました。(続き) CyclicRotation coding task - Learn to Code - Codility

前提

以下の条件で配列が生成される

  • 要素: N個
  • シフト数: K回
  • 要素は配列の終端に達した後、シフトすると先頭に移動する

func Solution(A []int, K int) []int は 配列を取得すると、K回シフトさせた配列を返します。

アルゴリズムを組み立てる際の情報

  • NとKの範囲は[0..100]
  • 要素の整数範囲は[−1,000..1,000]

Sample Data

data1

A = [3, 8, 9, 7, 6] K = 3

data2

A = [0, 0, 0] K = 1

data3

A = [1, 2, 3, 4] K = 4

Code

package main

import (
    "fmt"
)

func main() {
    // 問題文の仮定リスト
    intList := []int{3, 8, 9, 7, 6}
    fmt.Println(`before:`, intList)
    fmt.Println(`rotated:`, Solution(intList, 3))
    fmt.Println(``)

    intList = []int{0, 0, 0}
    fmt.Println(`before:`, intList)
    fmt.Println(`rotated:`, Solution(intList, 1))
        fmt.Println(``)

    intList = []int{1, 2, 3, 4}
    fmt.Println(`before:`, intList)
    fmt.Println(`rotated:`, Solution(intList, 4))
    fmt.Println(``)

}

// Solution の概要
// arg1: A []int [−1,000..1,000]の範囲の値をもつ[0..100]の要素数で構成された配列
// arg2: K int [0..100]の範囲をもつ数値
// return: arg1 を arg2 右側にシフトさせた配列
func Solution(A []int, K int) []int {
    // 要素数が0,もしくは1の場合シフトさせても結果が変わらないので
    // 早期リターンする
    if len(A) == 0 {
        return A
    } else if len(A) == 1 {
        return A
    }

    // 取り出した数値を確保する領域
    var popInt = 0

    // K回分要素を右にシフトさせる
    // 厳密には要素を取り出して、取り出す前の要素と取り出した要素を結合する
    for index := 0; index < K; index++ {
        // 終端から要素を取り出す
        popInt = A[len(A)-1]
        
        // 終端を取り除いた要素を作成
        A = A[:len(A)-1]

        // 要素を先頭に追加した配列を結合して作成
        A = append([]int{popInt}, A...)
    }

    return A
}
結果

before: [3 8 9 7 6]
rotated: [9 7 6 3 8]

before: [0 0 0]
rotated: [0 0 0]

before: [1 2 3 4]
rotated: [1 2 3 4]

解説

あまり書くことがありませんが、強いて言えば論理演算子を使わないことですかね。
論理演算子を使うと、頭の中でパターンを想定しなければなりませんが条件式が一つの時と比べて 考えることが多くなりバグを生む可能性が高くなります。

しょうもないヒューマンエラーを生んで悩む可能性を孕むよりは、多少の美しさは捨てるべきだと思っています。
美しさ = 可読性ではないですからね。