SIMフリースマホを買った

はとバスです.

私事で恐縮なのですが,私は今月の23ごろから,アメリカはサンフランシスコに行って来ます.

内容としては大学のイベントとしてなのですが,これで約二週間ほどの滞在となります.

そこで色々とプロトタイピングとかして来る予定なのですが.

今使ってるスマホがクソみたいな使い心地なので,simフリー端末を新しく購入しました.

今使ってるスマホ

今使ってるスマホは, FUJITSUの ARROWS NX F-04G .外見がかっこよくて二年前に購入しました.

スペックとしてはこんな感じ.(NTT Docomo 公式サイトより)

f:id:flying_hato_bus:20170813223306p:plain

スペック上は今でも十分通用するスペックだと思います.

しかし,今僕の手元にある端末は正直ハズレでした.

理由を少しばかり述べていきましょう.

1. そもそも購入して3日後にメーカーが発売停止

これを購入したのが,2015年7月25日ごろだったと思います.その当時,高校の友人にこのスマホを見せていたところ.「お前のそのスマホw,発売中止のやつじゃんwwwww」と言われました.

www.nttdocomo.co.jp

はい.

ハズレを引いたと思いました.

買った当初は感じていなかったのですが,一ヶ月ほど使い続けていると,様々な問題点が出て来ました.

2. 熱くなる

爆熱です.めちゃくちゃ熱いです.引くほど熱いです.

何かするとすぐに発熱します。発熱すると操作がだんだん困難になります。

GPSを使うアプリ,Google map や ポケモンGOなんかやった日には10分も持たずに電源が落ちます.

車を持っていて,ナビがわりに使おうとしたのですが,近場でも全く機能しない始末.

別に何かアプリを立ち上げている状況でこれならいいのですが,運が悪いと何もしていないのに突然発熱して,ガリガリバッテリーを食うだけ食って,死んでいきます.

これはバッテリーに良くない事なのですが,充電しながら使うとしても,充電開始から2,3分で熱くなって来て,そもそも電源を落とさなくてはいけなくなって来ます.

これ,冬場は結構重宝しました.アッタカイ……

3. Chromeとの相性が最悪

最悪です.何がって?

検索バータッチしてキーボードが出て来るのに平均して15秒以上かかるんです

これ,めちゃくちゃ困ります.

「あ,これなんだっけ」

ってときに,さっとスマホを出して,検索をしようとするときに,アドレスバーをタッチするんですが,キーボードが出るまで15秒以上を要します.

フラストレーションしかたまりませんね.

相手に何かを見せたいとき,これだと相手にも無駄な時間を与えてしまいます.

ちなみに,これはAndroid 6.0にしたら治ったのですが.これ以前にChromeを起動した瞬間から爆熱天使ドクロちゃんになります.電池がクソほど減ります.「ぴぴるぴるぴるぴぴるぴ〜♪」

f:id:flying_hato_bus:20170813225234j:plain

いいところ

f:id:flying_hato_bus:20170813225523j:plain

新しいスマホ

新しいスマホHuawei P10 lite のサファイアブルー.(めちゃくちゃかっこいい)

amzn.asia

スペック的にけっこうハイスペック.それでいて3万円ほどとリーズナブルな値段.何よりも青に惹かれました.

中韓に敵意もなにもないのでこれでいいかなと,というかITの分野だったらあっちの方が進んでるしなあ.

そんなこんなで購入しました.simカードは今のARROWSに刺さっているdocomoのヤツです.

海外で使うと行っても,空港でモバイルwifiを借りる予定なので,simカードは飾りみたいなもんかなとも思います.

スマホは水曜日までには来るそうなので,来てから詳細をレビューしようかと.

アンキパンを作った

どうもこんにちは,はとバスです.

今の時期の大学生はよくtwitterで,「テストガー」「ウワーーーラクタンシターーーー!!!」

など,嘆きの言葉が散見されます.そうです.

テスト期間

なんですね.

テスト期間に,よくやることとしては,「ただひたすらに問題を解く」「部屋の掃除」「暗記」「こんなクソみたいなブログの記事を書いちゃう」などがあると思います.

ん?暗記……?暗記……あん……き……

フワワワ〜〜ン……

f:id:flying_hato_bus:20170804073915j:plain

なんか…そんなものが……どこかで……

f:id:flying_hato_bus:20170804073939j:plain

ウ〜ン……暗記…あんき…

f:id:flying_hato_bus:20170804074007j:plain

あん肝食べたい……

f:id:flying_hato_bus:20170804074033j:plain

違う違う……アンキ….アンキ..パン……

f:id:flying_hato_bus:20170804074204j:plain

アンパン……違う…….

f:id:flying_hato_bus:20170804074223j:plain

f:id:flying_hato_bus:20170804074242j:plain

アンキパンですね.

と言うわけでアンキパンを錬成します.

使うものはたったこれだけ.手軽ですね!!!

  • 毎朝の食パン 6枚 108円
  • コーヒー牛乳 108円
  • レーザーカッター 200万円

アンキパンを作るためにはどうやら 2,000,216円が必要っぽいです.

そんなこと言ってないで作ってしまいます.テストまで時間が足りません.

作り方もいたって簡単.

f:id:flying_hato_bus:20170804081321p:plain

まずは覚えたいページを探します.

これをスクリーンショットします.

次に使うのはイラレ,これで印刷データを作ります.

f:id:flying_hato_bus:20170804075806p:plain

原作では,ノートに直にパンを貼り付けているので,文字が逆になるだろうと思い,文字を反転させます.

あとはレーザーカッターにデータを送って.

印刷!!

レーザーカッターに印刷させている間,ちょっとぐれーともす先生の本とかを読んでいれば有意義に時間を潰せるかと思います.

そんなこんなでできたのがこれ.

f:id:flying_hato_bus:20170804080313j:plain

文字が潰れまくってます.まあ,これでもアンキパンになっていると思うので食べます.

むしゃむしゃ……

むしゃむしゃ……

僕高校の時の化学を真面目にやっていなくて普通に通知表に2とかついてたんですけど,多分CO2レーザーのせいでめちゃくちゃ変な匂いがするんだと思います.

焼いたところがめちゃくちゃ臭いです.食えないことはないですが.

ちなみに,アンキパン以外にも,色々と使い道がありそうです.

ドカベンの文字をパンに書き込んだりできます.

そんなこんなやってたら,落としてはいけない授業を落としそうになっています.

最後に,僕が今回この記事を書くことで思ったことを言おうと思います.

f:id:flying_hato_bus:20170804080958p:plain

どうもありがとうございました.

PythonでI2Cを使う際のコマンドをまとめた

趣味が趣味なので,Raspberry piPythonで I2 Cを使うことが多い.

しかしいつもコマンドを忘れるので,自分のメモ用として今回の記事を書きます.

実際にRaspberry piでI2 Cを使う際の設定なども書いていきます.

実行環境としては Raspberry pi 3 + Python 3.6.0 です.

Raspberry pi側の設定

まずはPythonのI2 Cライブラリをインストール

$ sudo apt-get update
$ sudo apt-get install i2c-tools

これでとりあえずPythonのI2 Cを使用するライブラリをインストールします.

そもそも最初の状態ではRaspberry piはI2 Cを使用することができないので,設定画面から有効にする.

そのためにはまず,

$ sudo raspi-config

Raspberry piの設定画面を開きます.

f:id:flying_hato_bus:20170802193218p:plain

ここの 5.Interfacing Optionを選択.すると,色々なものを有効/無効化するところに遷移するので.この先の P5 I2Cを選択

f:id:flying_hato_bus:20170802193310p:plain

この先で色々聞いてくるので,適当に enable ってすればおkです.

最後に Pythonで I2 C-busをコントロールするためのライブラリである 「Python-smbus」をインストールします.

 $ sudo apt-get update
 $ sudo apt-get install python-smbus

これで一通りRaspberry pi でI2 Cを制御できるようになりました.

多分これで sudo i2cdetect -r -y 1などを打つと,下のような表示がされるようになるはずです.ダメだった場合,1の部分を0に変えてみてください.

$ sudo i2cdetect -r -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

こんな画面が出てくれば大丈夫です.この画面は,実際にI2 Cデバイスが接続された際,アドレスが表示されます.

例)

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- 64  -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

この場合,アドレスは 0x64になります.

本題

と言うわけでリファレンスから抜粋,下のカッコでざっくりと和訳しています.

long write_quick(int addr)

Send only the read / write bit (読み取り/書き込みビットだけを送信)

long read_byte(int addr)

Read a single byte from a device, without specifying a device register. (デバイスレジスタを指定せずに、デバイスから1バイト読み出し)

long write_byte(int addr,char val)

Send a single byte to a device. (1バイトデバイスに送る.)

long read_byte_data(int addr,char cmd)

Read Byte Data transaction. (トランザクションデータをデバイスから読み出す)

long write_byte_data(int addr,char cmd,char val)

Write Byte Data transaction. (トランザクションデータを書き出す)

long read_word_data(int addr,char cmd)

Read Word Data transaction. (トランザクションデータを読む)

long write_word_data(int addr,char cmd,int val)

Write Word Data transaction. (ワードトランザクションデータを書き出し)

long process_call(int addr,char cmd,int val)

Process Call transaction. (プロセスを呼び出す)

long[] read_block_data(int addr,char cmd)

Read Block Data transaction. (ブロックデータトランザクションを読み取り.)

write_block_data(int addr,char cmd,long vals[])

Write up to 32 bytes to a device. This fucntion adds an initial byte indicating the length of the vals array before the valls array. Use write_i2c_block_data instead! (デバイスに最大32バイトを書き込み.ただしこの関数は,val配列の前にvals配列の長さを示す最初のバイトを追加する必要がある.代わりにwrite_i2c_block_dataを使用しなければいけない)

long[] block_process_call(int addr,char cmd,long vals[])

Block Process Call transaction.
(プロセス・コール・トランザクションをブロック.)

I2C Access Functions

long[] read_i2c_block_data(int addr,char cmd)

Block Read transaction. (トランザクションデータをブロックで読み出し)

write_i2c_block_data(int addr,char cmd,long vals[])

Block Write transaction. (トランザクションデータをブロックで書き出し)

なんか絶対和訳を間違っている気がします.(気にしない)

何か間違いがあった場合,コメント等で教えてもらえると幸いです.

たまには真面目にPythonのお話をしてみる

どうもはとバスです.最近めちゃくちゃ暑くてかないませんね.

最近,トランプとデートした話や,エアコンが部屋になくてIQがマイナスに振り切れてるようなブログの記事を書いていて,さすがに友人たちに頭を疑われ,父親心療内科の受診と実家での休養を勧められたので,今日は真面目にブログを書きます.

Pythonのリスト内包表記と辞書内包表記

Pythonでよく言われるのが「速度」

速さが足りない!

f:id:flying_hato_bus:20170715003537p:plain

そう,速さが足りません.

Pythonはインタプリンタで一行ずつの処理をしているわけで,圧倒的に遅いという悲しい性を持っています.それに加えてfor文などは,一度リストを作成し,それを参照することでループをさせています.つまり,大きいリストを作れば作るほど,実行には時間がかかります.

それを一発で解決するのが今回お話をするリスト内包表記と辞書内包表記,for文の中で,新たにリストを作成する時,これらを使うとプログラムを短く,かつ速くすることができます.

普通のforループで,偶数だけを要素とするリストを作成する.
hoge=[]

for i in range(5000):
    if i%2 == 0:
        hoge.append(i)

print(hoge)

やっていることは,

最初に0から5000までのリストを作り,その要素の一つを変数 i と置く.

そのiを2で割って,0になるかどうかで判定.

0になった場合,リストに追加する.

ただこれだけ.

Cで書くとこんな感じ.

int i,j=0,huga[5000];

for(i=0;i<5000;i++){
    if(i % 2 == 0) {
        huga[j] = i;
        j++;
    }
}

Pythonでこれを実行すると遅くなる理由が二つある.

  1. 条件を満たす度にリストオブジェクトのappendを参照する

  2. appendをそもそもpythonの関数として呼び出している.

この二つです.この二つがこのループを遅くさせている原因なのですが,参照をループ外で定義してあげればある程度は早くなってくれます.

しかしappendが邪魔をしてしまうので,appendを使わないリスト内包表記のほうが結果的に早くなります.

これをPythonのリスト内包表記を使用して書くとこうなります

hoge = [i for i in range(5000) if i % 2 == 0] 

一行だけで済ますことができます.

説明

Pythonのリスト内包表記の基本構文はこんな感じ,これに色々修飾して書いていくのが多いです.

[変数 for 変数 in iterator]

今回はこのリスト内包表記に後置ifで判別させています. (原則として,Pythonでは後置ifが使用できませんが,リスト内包表記の時だけは使用が可能)

後ろについているif文の条件を満たす時だけ,hogeのリストに値が追加されます.

いちいちリストを作成しなくても,これで要件に応じた処理をできるので,そりゃfor文よりも速くなりますよねって話です.

ちなみに,後ろにくるのはif文で処理できるものなら何でも大丈夫で,例として関数の返り値などが使用できます.

辞書内包表記

次に辞書内包表記です. やっていることは,リスト内包表記を辞書にしただけなのですが,これがなかなか使いやすい.

辞書内包表記の基本構文はこんな感じです.

{key : value for 変数 in iterator}

key,valueともに変数を用いた値を代入することができます.

たとえば,100までの値をkeyとvalueにした辞書を作りたいときは

nya = {str(i) : i for i in range(100)}

こんな感じでできます,ちなみにkeyはstr型ではないとエラーが出るので,整数などをkeyにしようとする際には注意が必要です.

は?これじゃリスト内包表記とほぼ同じじゃん,何言ってんのw

こう思う方もいるかもしれません.

しかし,辞書内包表記は,イテレータの部分を辞書にすることで真価を発揮することができるようになります.

たとえば,辞書のkeyとvalueを関数に飛ばし,帰って来た値を新たに辞書のvalueの部分に代入することができます.

def nyan(noc,n):
    s = "ねこが{}匹 ".format(noc)
    nyaa = "にゃあ"
    neko = s+nyaa*n

    return neko

nyandict={'1':2, '2':4, '3':6}

neko_nyan = { k : nyan(k,v) for k,v in nyandict.items()}

print(neko_nyan)

=> {'1': 'ねこが1匹 にゃあにゃあ', '2': 'ねこが2匹 にゃあにゃあにゃあにゃあ', '3': 'ねこが3匹 にゃあにゃあにゃあにゃあにゃあにゃあ'}
 

こんな感じで,key,valueを引数とした関数を要素にもできます.

forループで書いていってもいいのですが,それだと冗長,そして時間がかかるので,個人的には可読性が少し下がりますが, 辞書内包表記を使用したほうがいいかなと思います.

上のにゃあをforループを使って書いた場合.

for k,v in nyandict.items():
    neko_nyan2[k]=nyan(k,v)

print(neko_nyan2)

forループの方がよくね?って思った方,僕も同感です.

それでは実家に帰って来たので,父親に連れられ心療内科からの隔離病棟で優勝して来ます.ありがとうございました.

熱いよーーーー助けてよーーーーー

あああああああっっあついwwwwwあついwあつwwwあつつつつつつううあああつつつあつあつあつwwwwwwwwww

あつwあちちwあちwwwwwww

アチュチャチャアチュイアチュイアチュイイイイイイイイイイイaaaaaaaaaaaaaaaaaaaaaa

ンコホォwアチュイノオオオオアチュイノタシュケテエエエエエエエエエエエエエエエエエエエエ

アチュシュギテアカチャンニナッチャッタバブwバブバブwwwwwブブッブフッブwwwwwwwwwwwwwwww

トウチャン!!!!! カアシャン!!!! ボキュニエアコンカッテカッテ!!!!!!!!!!!!

カッテクレリュウウウウウウウウウウウウウウウウウウウウウウウウウウ!?!?!?!??????

チュイノオオオオアチュイノタシュケテエエエエエエエエエエエエエエエエエエエエあつつつつつつううあああつつつあつあつあつwwwwwwwwwwいwwwwwあついwあつwwwあつつつつつつううあああつつつあつあつあつwwwwwwwwww

イアチュイイイイイイイイイイイaaaaaa

トウチャン!!!!! カアシャン!!!!トウチャン!!!!! カアシャン!!!!トウチャン!!!!! カアシャン!!!!トウチャン!!!!! カアシャン!!!!トウチャン!!!!! カアシャン!!!!

チュイノオオオオアチュイノタシュケテエエエエボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!ボキュニエアコンカッテカッテ!!!!!!!!!!!!、「、、、ヲ、## ィ、ェ 」ー」ア」イ」ウ」皀筌� 」リ」ル」レ竺軸宍雫七 而耳自蒔・ゥハクサ嵂ス、ィ、ェ 」ー」ア」イ」ウ」皀筌� 」リ」ル」レ竺軸宍雫七 而耳自蒔・ゥハクサ嵂ス、ア・ム・ソ。シ・�オ。ヌス。ヲクヲオ�。チ。ス。ン。�。ュカア・ム・ソ。シ・�オ。ヌス。ヲクヲオ�。チ。ス。ン。�。ュカ」イ」ウ」皀筌� 」リ」ル」レ竺軸宍雫七 而耳自蒔・ゥハクサ嵂ス、筌� 」リ」ル」レ竺軸宍雫七 而耳自蒔・ゥハクサ嵂ス、ィ、ェ 」ー」ア」イ」ウ」皀筌� 」リ」ル」レ竺軸宍雫七 而耳自蒔・ゥハクサ嵂

jupyter notebookでなんちゃってGUI

どうもはとバスです.最近は大学の研究室にいることが多いです.

今回は研究室でやったことについてです.

現在やっているのは自動車の自動走行です.

大学のレーザーカッターや3Dプリンターを使って,ある程度は車体ができたので,これからは実際に走行させ,データを収集するというところまで来ています.

そこでやろうとしたのがjupyter notebookを使用したコントロールです.

jupyter notebookに入っているのはpythonです.

pythonでよく使われるGUIツールの開発は,Tkinterというツールです.

これを使えばすぐにGUIツールを作ることができ.ボタンやスライダもすぐに作成できます.

さっそくこれを使ってコントローラを作ろうとしましたが.壁がありました.

jupyter notebookというのはssh接続でraspberry piと接続しています.

sshでは,原則ではGUIを飛ばしてくることはできず,エラーが出てしまいます.

そのために,他のライブラリを使用する必要がありました.

そこで出てくるのが, ipywidgets というライブラリです.

ipywidgetsって何よ

という話があります.そもそもこれは何かという話なのですが.jupyter notebookでインタラクティブGUIを作成できます.

作成できるものとしては,ボタンやスライダや入力フォームなどを作成できます.

これが動くのはjupyter notebook上なので,Tkinterのように,GUIの画面を飛ばしてくる必要がなくなります.

これを使用することで,Raspberry piを同一LAN上で制御し,なおかつそれっぽいGUIを使用することができます.

ipywedgetsのドキュメントはこちら,ここを見れば一通り使うことはできると思います,

僕がまとめたipywedgetsのgithubこちら,ここで一から解説するとなると修羅の道になると思うので,参考までにこちらをご覧ください.

ちなみに,これを使って,僕はラジコンのコントローラーを作成しました.

こちらがその動画です.

PythonでCounting Sortした

たまには真面目に記事を書きます.

今大学でやっているアルゴリズムの授業で書いたものです.

実行速度で差をつけろ!というときは,CやC++などで書くのがメジャーで,Pythonスクリプト言語で,逐次実行というところからすると,やはり遅くなってしまいます.

僕も大体の部分ではCを使って書いていたのですが,今回始めてPythonでじっくり書きました.

この大学のアルゴリズムの講義では会津大学のAOJというサイトを使用し,そこに用意されている問題をACさせることが,授業の課題という感じです.

今回の問題はこちら

問題を要約すると,入力された数字を計数ソートにより昇順に並べ換えるという問題です.

これをするためには Counting sort という手法で数字を並べ換える必要があります.

やり方としては以下の通り

  1. キー(配列Aのデータ)を数え上げるための配列Cとソートのための作業用配列Bを用意する
  2. 配列Cを利用して,配列Aのデータの出現頻度を数える
  3. 配列Cが保持したキーの累積度数分布を求める
  4. (配列Cの)累積度数分布に従って配列Aから配列Bにデータをコピーする
  5. 必要な場合,配列Bから元の配列Aにデータをコピーする

累積度数分布って何ですか?

累積度数分布とは,その値がいくつあるか?という分布です. 例として,以下のような数列が与えられたとき.

1 5 2 3 1 1 3 3

この場合,要素数は8,分布が均等であれば,1~8がそれぞれ1つずつ存在することになります.

実際は重複がいくつかあり,この場合の累積度数分布は f:id:flying_hato_bus:20170602002701p:plain

こうなる,あとはこのリストを分布に沿ってコピーすればいいという感じです.

実際のコードはこんな感じ,sort内のmはカウントをする配列の数になる.count = [0]*(m)の表記は,これだけで要素を0で初期化が出来ます.

ここまで言って何なんですが,このコードの中では累積度数分布を使用していません.

count[a] += 1 の部分で出現回数の計算をし,

for c in range(count[a]):
            array[i] = a
            i += 1

で値の出現回数だけ繰り返して元のリストに値をコピーしています.

サンプルにするとこんな感じ,print部分でごちゃごちゃしているのは出力に制限があり,それに当てはめた結果がこのようになりました.

ただただ出力したい場合は print(li)で出力が可能です.

def counting_sort(array, maxval):
    m = maxval+100
    count = [0] * (m)
    for a in array:
        count[a] += 1
    i = 0
    for a in range(m):
        for c in range(count[a]):
            array[i] = a
            i += 1
    return array
 
if __name__ == '__main__':
    N = int(input())
    l = list(map(int, input().split()))
    a = 0
    li = counting_sort(l, N)
    for a in range(N-1):
        print(li[a], end=" ") 
    print(li[N-1])

実行例

入力1

6 1 1 4 5 1 4

出力1

1 1 1 4 4 5

入力2

10 2 2 2 1 1 5 5 9 1 1

出力2

1 1 1 1 2 2 2 5 5 9

入力3

100 0 33 43 62 29 0 8 52 56 56 19 11 51 43 5 8 93 30 66 69 32 17 47 72 68 80 23 49 92 64 69 51 27 90 24 35 20 44 10 62 84 63 1 10 36 76 31 29 97 75 91 90 44 34 25 29 30 27 26 43 34 4 60 49 20 56 32 72 13 90 9 19 5 95 49 27 19 97 24 96 49 56 84 93 45 7 6 9 54 52 65 83 38 1 90 30 37 95 56 63

出力3

0 0 1 1 4 5 5 6 7 8 8 9 9 10 10 11 13 17 19 19 19 20 20 23 24 24 25 26 27 27 27 29 29 29 30 30 30 31 32 32 33 34 34 35 36 37 38 43 43 43 44 44 45 47 49 49 49 49 51 51 52 52 54 56 56 56 56 56 60 62 62 63 63 64 65 66 68 69 69 72 72 75 76 80 83 84 84 90 90 90 90 91 92 93 93 95 95 96 97 97

このように間違いはなく,実際にソートがされているということが分かる.