【学問のすすめ】中世ヨーロッパ写字生のように黙って静かに手を動かすブログ

これまで習ったことや学んだことを記事にまとめています。ITネタとChromebookネタが多いです。

【Python】受け取った文字列をシャッフルして返すコード「front_back.py」を書いてみた(ソースコードあり)

f:id:pesia_one:20180820000140p:plain:w400

Python3で受け取った文字列をある規則でシャッフルし返却するコードを書いてみました。簡単な解説もつけてみます。 今回はあらかじめ下記のコードが与えられており、2行目の「# ここになにがしかのコードを入力する」をどうするかを考えます。

def front_back(a, b):
# ここになにがしかのコードを入力する

print(front_back('abcd', 'xy'))
print(front_back('abcde', 'xyz'))
print(front_back('Kitten', 'Donut'))

 

はじめに

コードの要件

今回書くコードの要件は下記の通りです。

  • 要件1:2つの文字列aとbを受け取り値を返却する
  • 要件2:関数front_backを作成しその中で文字列を処理する
  • 要件3:返却する文字列は「aの前半」+「bの前半」+「aの後半」+「bの後半」とする
  • 要件4:関数front_back内では受け取った文字列を2分割する
  • 要件5:文字列の長さが偶数であれば真ん中で分割する
  • 要件6:文字列の長さが奇数であれば、前の部分文字列を1文字多くする

 

入力される文字列と出力される文字列

入力される文字列と出力させる文字列はそれぞれ下記の通りです。

  • 入力1:a = abcd , b = xy
  • 入力2:a = abcde , b = xyz
  • 入力3:a = Kitten , b = Donut
  • 出力1:abxcdy
  • 出力2:abcxydez
  • 出力3:KitDontenut

 

コード書いてみた

正解のコード

正解のコードは下記です。(Python3.2.5で動作を確認)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def front_back(a, b):
    a1 = len(a)
    b1 = len(b)
    a2 = int(len(a) / 2)
    b2 = int(len(b) / 2)
    # ここでintで型変換を行わないと文字列の取得でエラーが発生する

    if a1 % 2 == 0 and b1 % 2 == 0:
        return a[:a2] + b[:b2] + a[-a2:] + b[-b2:]
    # aとbが偶数の場合
    
    elif a1 % 2 == 0 and b1 % 2 != 0:
        return a[:a2] + b[:b2+1] + a[-a2:] + b[-b2:]
    # aが偶数でbが奇数の場合 

    elif a1 % 2 != 0 and b1 % 2 == 0:
        return a[:a2+1] + b[b2] + a[-a2:] + b[-b2:]
    # aが奇数でbが偶数の場合

    elif a1 % 2 != 0 and b1 % 2 != 0:
        return a[:a2+1] + b[:b2+1] + a[-a2:] + b[-b2:]
    # aとbが奇数の場合

print(front_back('abcd', 'xy'))
print(front_back('abcde', 'xyz'))
print(front_back('Kitten', 'Donut'))

# 要件1:2つの文字列aとbを受け取り値を返却する
# 要件2:関数front_backを作成しその中で文字列を処理する
# 要件3:返却する文字列は「aの前半」+「bの前半」+「aの後半」+「bの後半」とする
# 要件4:関数front_back内では受け取った文字列を2分割する
# 要件5:文字列の長さが偶数であれば真ん中で分割する
# 要件6:文字列の長さが奇数であれば、前の部分文字列を1文字多くする

# 出力1:abxcdy
# 出力2:abcxydez
# 出力3:KitDontenut

 

下記URLのGitHubリポジトリにも同じコードを掲載しています。

https://github.com/a1852rw/aiit_001_system_programing/blob/master/lesson_001/010_front_back.py

 

解説

「正解コード」の中には書かれていない部分について説明します。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

1行目はshebang(シバン)です。そのファイルがどのプログラムで実行されるかを指定します。 このコードではPython3であることを明示するために書き込んであります。shebangについて詳しくは下記のような解説ページを参照してください。

#!/bin/sh は ただのコメントじゃないよ! Shebangだよ!

2行目ではこのファイルがUTF-8で書かれていることを示しています。
これを指定することでファイル内の日本語が文字化けしないようにすることができます。

 

a1 = len(a)
b1 = len(b)

文字列a,文字列bの文字数を変数a1,b1に代入しています。

 

a2 = int(len(a) / 2)
b2 = int(len(b) / 2)

文字列a,文字列bの文字数を1/2にした数を変数a2,変数b2に代入しています。 ここではなぜかfloat型(浮動小数点型)で数値が返却されますint型(整数型))への変換を行わないとエラーになります。

 

if a1 % 2 == 0 and b1 % 2 == 0:
        return a[:a2] + b[:b2] + a[-a2:] + b[-b2:]

if文で条件分岐を設定します。「% 2 == 0」で「2の商が0」つまり「2で割り切れる数」=「偶数」を判定しています。
a[:a2]は「文字列aの前からa2番目までの文字列を抽出」の意味です。
同様にa[-a2:]は「文字列aの後ろからa2番目までの文字列を抽出」の意味になります。文字列操作では文字数をint型(整数型)で指定しないとエラーになります。

 

elif a1 % 2 != 0 and b1 % 2 != 0:
        return a[:a2+1] + b[:b2+1] + a[-a2:] + b[-b2:]

elif文で条件分岐を設定します。「% 2 != 0」で「2の商が0ではない」つまり「2で割り切れない数」=「奇数」を判定しています。
a[:a2+1]は文字列aの前からa2番目+1文字までの文字列を抽出」の意味です。

 

あとがき

文字数を計算する部分「len(a) / 2」ではまりました。
「len(a)」ではint型(整数型)でaの文字数が返却されますが、これに「/2」をつけるとなぜかfloat型(浮動小数点型)になることに気が付けずエラーを修正できませんでした。
最終的に一か所ずつprint関数で出力を確認したときに気が付くことができました。
ここだけで2日かかりましたこの仕様は理不尽だと思います。