2015年10月8日木曜日

Pythonのリスト内包表記その2

リスト内包表記を知らなかった私が、前回(http://blackstraycatreboot.blogspot.jp/2015/10/python.html)リスト内包表記はリストの条件付き再リスト化と覚えたばかりだが他にも直接文字列を列挙したりできるらしい。

つい最近
【漫画版: 女子高生プログラマーの大バトル!〜コボール文明の逆襲〜|paizaオンラインハッカソン6】>【遺跡発掘ゲームで古代コボール王Ⅳ世を撃破せよ!|緑川つばめ】
(https://paiza.jp/poh/joshibato/tsubame)の簡単な問題にて

入力値+その値左側(10の位)+その入力の右側(1の位)を足して終わりという簡単な問題
初回は単純に


n=raw_input()
print int(n[:1])+int(n[1:])+int(n)


一度変数に格納してスライスで分解し、intへ変換しつつprint出力しました。
しかし、面白味が無かったので入力値を直接回答叩き込みたくなった。

ところが変数は分解しなければならず、入力値に直接スライスでは値をそのまま返せない。
変数のコピーさえあれいいのに・・・

そこで指定値for系で学んだリストの生成方法を思い出した
ループさせる場合【 for x in range(N) 】みたいな生成が一般的だが【 for x in[0]*N 】の方が生成が早くさらに【 for x in[None]*N 】の方が速い。
今回速度はさて置き、リストは【 [指定値]*数値 】でリストを生成すれば元値を複製できる。


[raw_input()]*3


これで入力値を3つに複製できた。
ですが値を切り出し、さらに数値にして合算する必要がある。

そしてついに話戻ってリスト内包表記!これならリストを列挙しつつしかも最終的な値を直接返せる!
リストに対するint変換は入力値周りで覚えたmapによりintに変換できるし、さらにそれに対して他の問題でやったリスト合算sumが使える。

なるほどこれは簡単に見えて総合問題なんだな(絶対違う)という事に。
だがしかし、ここで少し手が止まる。


print [x for x in[raw_input()]*3]


三回入力値を得られたが処理に変化を加える為の方法がない。
ここで1・2分くらい悩んでenumerateを思い出した。
リスト要素に対し値と要素番号を得られる。これでどうにかしよう。


print [b[::] for i,b in enumerate[raw_input()]*3]

スライスで切り抜くには【 変数[開始インデックス:終了インデックス:ステップ] 】となる。
だがここでまた思案。

iに入ってくるのは0・1・2これを要所に設定した場合格納値は(入力が27の場合)

b[i::]→["27","7",""]
b[:i:]→["","2","27"]
b[::i]→エラー(ステップに0は指定できない

んー惜しい・・・。

開始+0、終了+1なら(入力が27の場合)

b[i:i+1:]→["2","7",""]

んーこれでは全体が入らない。
同時に平行で移動する関係上範囲が一定なのは仕方がない

今が
b[0:1] #2
b[1:2] #7
b[2:3] #""


なので
b[0:1] #2
b[1:2] #7
b[0:2] #27
とかになってくれれば・・・ん?

これ、オーバー通る?
b[0:3] #27
通る

0・1の交互なんて連番なら簡単じゃないか数値の÷2のあまりでいい
じゃあ・・・

b[i%2:i+1:]→["2","7","27"]

キター。
それじゃあ、これにmapかけて

print map(int,[b[(i%2):(i+1)] for i,b in enumerate([raw_input()]*3)])
>>>[2,7,27]

sumで合算してやれば

print sum(map(int,[b[(i%2):(i+1)] for i,b in enumerate([raw_input()]*3)]))
>>>36

できたーーー!時間にして10分なんて難しい総合問題なんだ・・・。




今回の落ち(と、言うか今回はこれの為)
別な問題をやっている時にヒントとかいうのに気付いた

print ''.join([v for k,v in enumerate(raw_input()) if k%2 == 0])

なんか近いのを見たなぁこの黒魔術な感じ、と言うかさっきこの絶対やる必要のない遠まわりな感じの回答したよ。



さておき、今回の落ちが本編なのだが頭に書いた通り、直接文字列を列挙できる。
リスト内包は「リストを再リスト化」しかできないという理解だったが文字列を要素として一文字ずつ取り出すことができる。
上の式では一文字ずつ取り出し、カウンタを2で割ってあまりが0か1かで格納する値を決めて最後に空文字でリストを結合している。

というわけで、リスト内包はリストも文字列もリスト化できるという事でした。
これを書くのに長い毎ふりだったぜ・・・。




蛇足:
ただ、まぁもしもこういう感じにするならわざわざ0を判定するのはあれなので

print ''.join([v for k,v in enumerate(raw_input()) if not k%2])

こうでしょ?・・・いやまあこう言うのが可読性を落とす原因なんだけどね。
(値の返りが何と一致しているから処理されるという明示がなくなる為)
いやでもそもそもこの問題リスト内包してる時点で可読性激落ちですからね。

じゃあどうするのって話だがPythonですからそこは

print raw_input()[::2]

これだけでいいんですよ。

2015年10月7日水曜日

デフォPython高速化

Python2x系で数値読み込みループにinput()は使うな!

何故かと言うとinput()は式を求めているから。

数値を直接得るのに【 num=input() 】はメジャーな使い方である。
だが、これを数千数万とループで受ける場合話は別である。

最初に述べた通りinput()は式を求められている。
「つまりどういうこと?」と言う話だが
【 input() 】=【 eval(raw_input()) 】なのである。

たとえば300,000回程度forで数値入力の読み込みループを行い配列で受ける場合

=input()約2.1秒
=eval(raw_input())約2.1秒
=int(raw_input())約0.5秒

かなりおおざっぱな検証だがこれくらい差がでる。
【 input() 】と【 eval(raw_input()) 】が同じなのは同等の処理を行っているから当然の結果。
【 input() 】と【 int(raw_input()) 】では【 input() 】の方が簡潔に見えるが行わる処理は遠まわりしている事になる。
結果的に2倍以上の差が発生する。
※ちなみにintでは端数切捨てなのでそこは注意。


そもそも読み込みループを行うな!

何故かと言うとPython自体がもうループ処理自体が遅い。
「じゃぁどうするんだよ!」確かにそう言うのも仕方がない。

だが標準入力はほかにもある事を思い出してほしい。
具体的にはには以下のようにする。

import sys
mylist=list(map(int, sys.stdin.read().splitlines()))

readで連続で受け取りsplitlinesで分割。それをさらにmapを使い一括でintに変換する。
どれくらい早くなるのかというと

約0.17秒!int(raw_input())のさらに倍以上早い。
ただし、これは実際のケースではそんなにないのではないかと思う。
この問題に気付かされたのはPOHなので課題専用処理と言っていい。


ループはwhileよりもforを使え!

ループ回数が増える程whileよりもforのほうが処理速度が速い。
処理は処理として使いやすい方を使うのが正しいが処理速度がどうしても欲しい場合whileで行っている処理をforに置き換える事を検討すると良い。



リスト化はリスト内包を使え!

通常forでリストを追加する場合appendをチェックしている。
だがリスト内包を使った場合はリスト化前提の為その処理がない分速い。
しかもその処理時間は6割程度違う。つまり、通常forでリスト化して10秒ならリスト内包なら4秒で終わらせる事が出来る。

とにかく要素追加が遅いという事。逆にリスト等の要素追加でなければここまで差はでない。
ただしmap等forすら回さなくて良い場合はそちらの方が速い。

ループカウンタが不要なら[None]*数値を使え!

forの構造上値を渡しながらループする事になる。
通常であれば
【 for x in range(数値) 】だが、それよりも
【 for x in[0]*数値 】の方が速く、さらにそれよりも
【 for x in[None]*数値 】とした方が速い。

あくまでも大量のループを回すときにに空のリスト生成の方が速いという事。
ただし、rangeと[0]では割とさが出る様だが[0]と[None]では大きな差は無い。

ソートするならlist.sort()を使え!

自身を並べ替える為list.sort()はsorted()よりも若干ですが効率が良いです。
list.sort()の戻り値はNoneでsorted()との混乱を回避する為らしい。
といっても受けた値をソートできる為sorted()使っちゃうよなぁ。







後で追記する

2015年10月6日火曜日

Pythonは黒魔術であってはならない・・・だが

まぁもちろん魔術というのは揶揄した言い方なのですが今回コードゴルフでなるほろーと思ったこととか。

Pythonとは

Pythonはリーダビリティ(可読性)特化言語である。
その為、普通に打ち込みを行っている分にはみなが均一に読みやすいコードになり改修も楽で自身が忘れたコードでも読み返して見やすいそういう作りの言語です。

だが・・・黒魔術はなくならない。

ここで言う黒魔術はリーダビリティを失った何が書いてあるのかぱっと見ではわからないコードの事を指します。
黒魔術の主成分は主にワンライナーとコードゴルフです。
これに特化する事で新たな発見や効率化を生み出しますが基本的には何が書いてあるか解り難い魔術言語となります。
特にRubyは上級黒魔術と言っていいでしょう(何あれ?ホントぱっとみなんだか意味不明)。

と、どうでもいい前置きでしたが、つまりはPythonでも言語方針に反しリーダビリティを投げ捨て、さらには処理速度すら投げ捨ててでも暗黒面に身を染めようじゃないか!というお話。



私は初めからPython 3x系で独学したためほとんどPython 2x系との違いなんて気にしたことがありませんでした。
知ってた違いは
・2系ではxrangeの方が処理が早く、3系ではデフォルトでrangeは2のxrengeの処理で行われる。
・関数等が【 ()括弧 】が必須で2系では【print "aa"】とできたが3系では【print("aa")】でなければエラー
・2系のraw_input()は3系ではinput()になった
程度です。なのでまさか2系に「input()」があるとは・・・閑話休題。


コードテクニック

では闇Python黒魔術を始めましょう。
と言っても「or・and」あたりは胡散臭い処理ですがそれ以外はわりと普通のコードテクだったりします。
また、主にPython 2x系の話となります。

1.使いまわす関数を減らす

Pythonでは関数を変数に代入する事でその変数を関数として使う事が出来ます。
【i=raw_input】と定義すれば今後【i()】だけで呼び出せるのです。

たとえばraw_input()を2回以上使う場合4byte違いがでます。
p=raw_input;a=p();b=p()
a=raw_input();b=raw_input()

rangeの場合は2回では同byteですがメインコードが薄くなります。
r=range;a=r(6);b=r(9)
a=range(6);b=range(9)

intでは2回程度では2byte損です。
int=i;a=i("10");b=i("10")
a=int("10");b=int("10")

2.input()とraw_input()の違いを知る

これは完全にPython 2x系の話になります
input()とraw_input()の違いはinput()は式をそのまま評価します。
【input()】は【eval(raw_input()) 】とするのと同じです。
入力される式が正しくないとエラーが複数発生したり扱いが少し難しいですが入力が文字か数値かだけの場合【input()】で数値として値を受け取る事が可能になります。

今回の様に一度目のみ数値の入力、二回目以降は文字列等の場合かつその数値は数値として受け取りたい場合に非常に有益です。

一度目の入力を数値の5、二度目の入力が文字列”ABC”であれば
使い分けた場合23byte、通常のままの場合32byte、一文字定義で26byteとなり、使い分けた場合が最短になります。

a=input();b=raw_input()
a=int(raw_input());b=raw_input()
p=raw_input;int(i());b=i()

3.暗黙型変換と評価で格納値を変える

暗黙の型変換はifなどの評価において0をfalse、0以外の数値(not 0)がtrueになります。
また、空文字「""」はfalse、文字に値がある場合trueとなります。
それと同時に、リスト番号での評価式はfalseが0となり、trueが1になります。


・数値や文字列がboolで処理される

if 0:print"表示" #表示されない
if 1:print"表示" #表示される
if "":print"表示" #表示されない
if "a":print"表示" #表示される


・評価が値数値で処理される

print ("A","B")[true] #Bが表示される
print ("A","B")[false] #Aが表示される


4.orとandの遅延評価でifを減らす

主に行数を減らすワンライナー向け

orは「どちらか条件ならば」であり処理は左から行われる。
つまり、左が条件に達した時点て確定する。
逆に左がfalseで場合右が値として確定する。

True or "a"
上では左がTrueで確定しTrueとなり、後ろが評価されない。

False or "a"
上では左がfalseとなり"a"が値として確定する。


andはorの逆で「両方が条件ならば」であり同じく左から処理される。
つまり、左が条件に達せない場合後続は処理されない。

True and "a"
上では左がTrueの次の評価に入り"a"が値として確定する。

False and "a"
上では左がFalseであり、その後ろは評価されない。


ifの代わりに使う場合はこのようになる
条件 and True時 or False時


5.リストや配列追加にappend等を使わない

a=[];a.append("ABC")
ではなく

a=[];a+=["abc"]
と記述すれば5byte短くなる

6.処理系以外はセミコロンで並べる

行にif・for・whileが無いなら【 ; 】セミコロンで処理を並べる事が出来る。
だが、リスト内包表現は代入式の為セミコロンで並べる事が出来る。


7.複数の同じ内容の初期化

a=0;b=0;c=0 #これよりも
a,b,c=0,0,0 #これよりも
 a=b=c=0  #こう
 a=b=c="" #文字列ならこう

 a,b,c='1','2','3' #文字限定でよりも
a,b,c='123'      #こう

8.exec('処理'*数値)でループの代替をする

ループ速度と言うか繰り返し実行速度が有益か怪しいが普通にループ処理を書くより短くなる。
また、文字列として処理が入る為一行で書くことが可能になる。

a=0
for x in[None]*10:print(a);a+=1

a=0;exec('print(a);a+=1'*10)

この様に書ける。forがなくなる事でaの初期化をセミコロンで処理を後続に並べる事も出来る。
【 '処理' 】を連続で投げている事になる。
execはきた文字列を処理として展開実行する。
これにより疑似ループが完成するがスコープ周りなど注意が必要。

9.カウンタ無ループfor x in[0]*数値

ル―プカウンタが不要なら

for x in[0]*数値

とする。
inの後に【 [ 】を隣接することで1byte短くなるし、0リスト生成は処理も速い。
ただし[None]*nの方が最速。







後で追記する

【lambda】無名関数さえあれば短くなるしワンライナーもry
【三項演算子】でif・elseを一行にさらに入れ子も
【リスト内包表現】再リスト化・抜出し。for系なのに代入式なので「;(セミコロン)」でつなげる事も可能
【リスト内包表現が1つの場合両端の[]を消しても良い?】


最後に

それ、Pythonじゃなくていいよね?
処理速度ならC++、コード圧縮したい(とにかく短く書きたい)ならRubyで書きませんか?

やっぱり邪道なのです。
折角このPythonという言語自体がリーダビリティをが良いのこれを失わせるなんてとんでもない。
・・・だが(以下ループ)

以上です。

2015年10月5日月曜日

Paiza Online Hackathon略して「PHO」らしいよ

回文からそもそもこれなんなんだろうと思ってちょっとだけ調べた。
ちょっと触ったのはファーストコードだけ載せておく。
基本的にPython3のコードが好きなのだけれどこのサイトは処理速度を求められるため処理速度が気になった場合Python(Python2系)です。

・・・暇つぶしが必要な時にちょっと少しやろう。

新人女子プログラマの書いたコードを直すだけの簡単なお仕事です!|paizaオンラインハッカソンVol.1

https://paiza.jp/poh/ec-campaign

・概要:
第1入力は【「N (1 ≦ N ≦ 200000)」半角スペース「D (1 ≦ D ≦ 75)」】(NもDも整数)
第2入力はN回「p_i(10 ≦ p_i ≦ 1000000)」の入力(改行区切りで渡されるの意)
第3入力はD回「m_j(10 ≦ m_j ≦ 1000000)」の入力(改行区切りで渡されるの意)
(※C,C++のみ処理性能が高い為かNの最大は500000、Dの最大は300テストケースも異なる)

「p_i」リスト2つの組み合わせ合計が「m_j」以下で最も近い値をDのパターンだけ出力する。
「p_i」の組み合わせ全てが「m_j」の値を越える場合は「0(整数ゼロ)」を出力する。
「p_i」の組み合わせは「p_0+p_0」といった自身同士の組み合わせは含まない。

・ファーストコード(Python):

※テストケース1 : 2.30 秒。2以降はタイムアウト。制作者の意図に嵌り過ぎ

・途中コード1

※テストケース1 : 0.70 秒。2以降はタイムアウト。dequeなら?とお試しぐっと早くはなったがダメ

・途中コード2

※テストケース1 : 0.88 秒。2以降はタイムアウト。遅くなってゆく


・ラストコード(Python):

テストケース1 : 0.02 秒。
テストケース2 : 0.03 秒。
テストケース3 : 0.16 秒。

最終的に他の問題をやってきてから戻ってきた。forによる読み込みは遅いという事がほかの問題で知ったためsysをインポート。

ここら辺の入出力はCscriptと同じ感じ。
wscript.stdin.readline()
cscriptではこんな感じ。


更に指定値に割り込む要素番号をどうすれば早く知る事ができるかというのを調べてbisectにあたった(これ便利ー)。


処理要点のみ説明すれば以下
 campaignsの値段を商品一覧右挿入点取得(bisect_right同意味
 best&temp初期化
 strtよりendが大きい間
 エンド特定商品・最低値+最高値がcampaignsより低くなるまでendを下げる
 tempとして値段保持
 temp bestがtempを下回る間
 現状best
 一致で終了
 一致しない場合最小値を繰り上げ

それで後で調べたら最終問題はキャンペーン価格のみで通るらしい。
どういう事かと言うと、価格リストが増えるとキャンペーンへ価格の組み合わせが完成する率が高くなる。
今回の問題でいうと結果的に最終ケースはキャンペーン価格を表示するだけで良いとの事。ぐすん。


女子大生とペアプロするだけの簡単なお仕事です!|paizaオンラインハッカソンVol.2 

https://paiza.jp/poh/paizen

・概要:
第1入力は設置面【「H (1 ≦ H ≦ 130)」半角スペース「W (1 ≦ W ≦ 130)」】(HもWも整数)の
第2入力は設置可能行【D_i(1 ≦ i ≦ H)】「1が配置済」「0が空き領域」で0と1のW桁
 (例:Wが5の場合「01010」や「11110」の様に入力される)
第3入力は設置数【N(1 ≦ N ≦ HW)】最大は1x1が全マスとなるHxW
第4入力は設置種【「S_i (1 ≦ i ≦ N)」半角スペース「T_i (1 ≦ i ≦ N)」】
 サイズは【「S_i (1 ≦ S_i ≦ 300)」半角スペース「T_i (1 ≦ T_i  ≦ 300)」】
(※Java,C,C++,C#の場合「H」「W」の最大は130ではなく300)

上記条件で初期配置に対し、設置種それぞれ配置可能数を出力する。

・ファーストコード(Python):

・コードは後で書くとして、問題の所見:
値は1か0で来るので画面を越えない範囲でスライスの合計0なら配置可能。
左から右、上から下へ処理対象を移動し「A行B文字目」において、「B+T<=H」範囲内で「D_A行目[B:T]」をスライス。「A+S<=H」範囲内でA~A+S行目までを足して0ならば設置可能


天才火消しエンジニア霧島「もしPMおじさんが丸投げを覚えたら」|paizaオンラインハッカソンLite 

https://paiza.jp/poh/kirishima

マンガ版「エンジニアでも恋がしたい!」〜転職初日にぶつかった女の子が同僚だった件〜|paizaオンラインハッカソン4 Lite 

https://paiza.jp/poh/enkoi

■ドッキドキの転職初日、最初の仕事は炎上PJの鎮火!?

・ファーストコード(Python3):58 byte


■野田さんと飲みに行ける!?クソコードをささっと修正!

・ファーストコード(Python3):114 byte


■ゲームアプリ「パズウナ」の作成に挑戦!野田さんはよろこんでくれるかな!?

・ファーストコード(Python):181 byte

ちなみにsleepで検証してみたらテストケース4と5は最大の「300,000マス」区間は共に「150000マス」です。


マンガ版「俺の許嫁と幼なじみが修羅場すぎる」|paizaオンラインハッカソン5

https://paiza.jp/poh/enshura

■レナたんが俺の許嫁!?手紙の暗号を解読せよ!

・概要:奇数番目の文字列のみ表示

・ファーストコード(Python3):19 byte

解説:入力値を直接ステップ2でスライスする。19byteで済む。

■レナたんのパパが経営する会社の入社試験に挑戦だ!

概要:
第1入力は【N(1 ≦ n ≦ 210)】(Nは整数で必ず7の倍数)=【N(7 ≦ n=7*? ≦ 210)】
第2入力はN回「p_i(0 ≦ s_n ≦ 1000000)」の入力
1~7入力を1セットとして、各何番目の合計を7つ出力する。

・ファーストコード(Python):94 byte

先に↑を書いたけどいっそベタでもいいんじゃないかと↓を思いついたが長くなったのでやめた

■ミナミとレナ、どちらを選ぶか究極の選択です・・!

・ファーストコード(Python):12 byte

・ファーストコード(Python):14 byte

・そりゃレナでしょ?2byte短いもの(ぇ)

■障害が起きている会社のメインシステムを改修だ!!(レナルート)

・ファーストコード(Python): byte


■会社を辞めて、一から自分でアプリ開発を頑張るぜ!(ミナミルート)

・ファーストコード(Python): byte


漫画版: 女子高生プログラマーの大バトル!〜コボール文明の逆襲〜|paizaオンラインハッカソン6

https://paiza.jp/poh/joshibato

■ちょうどいい濃度のコーヒーを淹れ、古代コボール王Ⅳ世を撃破せよ!|食いしん坊ハッカー:六村リオ

https://paiza.jp/poh/joshibato/rio
・概要:

■古代コボールすごろくで古代コボール王Ⅳ世を撃破せよ!|天才ハッカー:霧島京子

https://paiza.jp/poh/joshibato/kirishima
・概要:

■遺跡発掘ゲームで古代コボール王Ⅳ世を撃破せよ!|なでしこハッカー:緑川つばめ

https://paiza.jp/poh/joshibato/tsubame
・概要:2ケタの整数N(10 ≦ N ≦ 99)に対して、N+Nの10の位+Nの1の位の合計
・例:27が入力された場合【27+2+7】となり【36】が回答となる

・ファーストコード(Python3):

・ラストコード(Python):



「え、妻が松江?」松江Ruby会議07協賛 回文作成プログラミングコンテスト|POH6+ 

https://paiza.jp/poh/joshibato/matsue-ruby

■最強の復活の回文

・概要:これを最初にやったので概要についてはこちら

・提出コード(Python):211 byte

2015年10月2日金曜日

回文最速版ALL0.02秒

paizaオンラインハッカソン6+
「え、妻が松江?」松江Ruby会議07協賛 回文作成プログラミングコンテスト|POH6+
https://paiza.jp/poh/joshibato/matsue-ruby

前回、前々回に引き続き例の回文です

Python 211byte


結果:https://paiza.jp/poh/joshibato/matsue-ruby/result/cf3ec175
All Test case  実行時間: 0.02 秒

最速で動かない事には話にならないという事で今回は取り敢えず速度優先。
前回、前々回でとにかく配列の増減で処理落ちが酷い事が解りました。
また、同じステップ条件のforが無駄であるという事でそこらへんから処理の高速化をめざしました。


・・・ただし、無駄が多いです!


ツイッターのハッシュを少し追うだけで【Python】【All Test case  実行時間: 0.02 秒】【135byte】らしいので絶対に何かもっといい処理方法があるはずです。

ちなみにPythonにおけるこのサイトでの最速は0.02秒より早くなりません。
第一問を直接printで回答しても0.01秒になりませんでした。



前置きが長くなりましたがそれでは説明。


■for n in[None]*int(i()):
前回説明通り、Pythonのforは処理構造がforeach文のそれです。
その為カウンタを必要としない場合rangeで数値リストを生成する必要がありません。
つまり入力の数だけループさせたい場合空のリストで問題ないとう事です。
リストの生成においては【[None]*数値】が恐らく最速です。
また、forではリストの生成が必須になる為それに処理を取られるもののwhileよりもforの方が処理が早い為forを使います。

■s=i();r=s[::-1]
入力を直接「s」に取得し、rに逆順文字列を保存。

■if s==r:
「文字列と逆順文字列が同じ=単独回文」として先に処理します。

■if c!="":l+=[c];c=""
今回も全テストケースで【重複するのが中央文字列しかなく、1種類しかない】という前提で記述してるため邪道感があります。
もし、既に文字が格納されている場合左文字列が確定するため「l」に追加します。
それと同時に「c」を空文字列戻します。

■else:c=s
「c」が空の場合、その値を代入します。

■else:
単独回文ではない場合

■if r in t:l+=[(s,r)[s>r]]
リスト「t」に逆順文字列「r」が含まれている場合「l」に追加します。
ただし、今回は取得置きに処理するため「abc」か「cba」どちらが変数「s」に格納されているかわかりません。
そこでこの処理です。【 (s,r) 】が簡易配列だと思ってください、【 [s>r] 】この条件式でTrueまたはFalseが返り、結果的にTrueで1がFalseで0として処理されます。
Pythonにおける文字列比較はa~zに従って大きいと判断されます。
これにより「abc」が格納されていようが「cba」が格納されていようが小さい方(昇順の文字列)が格納できます。

■else:t+=[s]
左文字列か除外文字列かまだわからない文字列はtempとしてリスト「t」に追加します。


■l.sort();a="".join(l);print(a+c+a[::-1])
最後に左文字列のリストをソート、さらにjoinにより空文字で結合します。
あとは出力しておしまいです。





以下蛇足
凄くどうでも良いけど所でなんで【Python】書けるの?


元々はだいぶ前に、友達が3D制御のスクリプトにPython使えるからという事で教えて的な感じで話があり、まぁ自分にも役に立つだろうと少しだけ触りました。
それまでは全く触った事がありませんでしたが普段使わない言語でも少し調べればif・for・配列くらい教えられればいいかなと。

ツイートで流れたのでちょっと面白そうと思って試しましたが、まず選べる言語で書けそうなのがPythonだけという・・・。
今回は思い出しながらと言うよりはほとんど調べ直しながらになったため苦戦しました。
結局他の言語で書いたのをPythonに置き直すようにしながら必要な関数等を調べました。


今回の落ち。
if・forで既に友達が挫折しました。



言語についてはjavaとC++それにPHPは少しだけ使ったことがありますがすっかり忘れました。
ここ最近では主にWSHのVBS、基本動作は大抵Cscript。
またHTAを合わせる事で簡易アプリを作ったりですね。
web周りではjavascriptをかなり触ったんですが最近は便利なライブラリが多く自作する事はほぼなくなりました。

あとはVBAも触りますが、VBSの知識がほとんど使いまわせるからと言う点と大抵のPCにエクセルが入っているので使い勝手が良いからです。
そういう意味でwindowsさえ入っていれば直ぐに作れて動かせるVBSとHTAは使い勝手が非常に良いです。

今後は「Windows PowerShell」とか覚えたいところではありますがついついVBSに・・・。
まぁ、今回は処理完成後も色々改善策を練ったりと勉強になりました(また忘れそうですけどね・・・)。

今回思ったことは「Rubyどれだけ短くかけるんだ・・・」って所と「Pythonおっそい!!」って所に尽きますね。
また、こういう機会があれば頭の体操程度にやってみようかと思います。


Pythonのリスト内包表記

例の回文の件で処理速度を早くするためにforが早くするにはとしらべていたらリスト内包表記がわりと速いらしい。
先に処理の比較を見た限りifを入れると結局は微妙な早さっぽい。

でもまぁまずは「リスト内包表記」なるものを使ったことが無い為調べる事に。
要約すると「作成済みのリストから条件をつけつつリストアップしながらさらに値に変更を加えつつ新しいリストを作成する事が出来る」です。

解りずらいので実際の式
mylist=range(5)
newlist=[x+2 for x in mylist if x > 2]
みたいな感じです。

変数=[xに変更を加えて格納 if x in 抽出元リスト if xが~なら]

処理順は右側、左側、中央
上の処理を順にみていきましょう

mylist=range(5)
newlist=[x+2 for x in mylist if x > 2]
先ずは右の処理からここはmylistからの抽出条件です。
forとinの間にある変数が対象各処理における変数で指定できます。

初回ループは0なので
if 0 > 2
となる為スキップします。
if 1>2
if 2>2
もスキップ

ついに抽出条件になりました。
if 3>2

続けて格納する前に処理を加える事が出来ます。
newlist=[x+2 for x in mylist if x > 2]
続けて左側、今回の場合は
3+2つまり5がリストに格納されます。

同じように次は4が処理され
4+2で6が格納されます。

>>>print(newlist)
[5,6]
となります。



・・・なるほどこれは便利そう。ただ、なかなか見づらいですね。