อ้างอิงจากโจทย์ Ruby #21
ผมทำไว้ 3 แบบ แบ่งตามระดับความโรคจิต
def problem21_1(input,n): ret = [] for i in range(0,len(input),n): ret.append(input[i:i+n]) return ret
def problem21_2(input,n): return [input[i:i+n] for i in range(0,len(input),n)]
problem21_3 = lambda input,n: [input[i:i+n] for i in range(0,len(input),n)]
แล้วก็เอามารันเทียบกัน
input = range(1,10) n = 3 for f in problem21_1,problem21_2,problem21_3: print f(input,n)
ผมนึกออกแค่นี้… หัวตื้อ
กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น
เล่นเฉลยซะหมด -_-"
เอาเวอร์ชั่นโรคจิตแบบไม่ใช้ lambda แล้วกัน เดี๋ยวมัน deprecate
def sep(i,n): return [i[j:j+n] for j in range(0,len(i),n)]range เป็นพระเอกใน solution นี้เลยแฮะ
เอาด้่วยคนสิ
def sep(list,n):
if list==[]:
return []
else:
return [list[0:n]] + sep(list[n:],n)
แต่แบบนี้พอสั่ง list[n:] มันจะ copy ใช่ป่ะครับ.... ช้าตายเลย
(อัีนแรก list[0:n] เนี่ยะ ยอมรับได้ เพราะว่าคิดเวลารวมก็เท่ากับวิ่งทั้ง list)
ทำไงไม่ให้ต้อง copy อ่ะครับ
แอบเพิ่ม arg ตัวที่ 3 เอาไว้ระบุ index โดยที่ค่าเริ่มต้นเป็น 0
อืม... ทีนี้ พอสั่ง input[i:i+n] มันก็ต้องวิ่งตาม pointer ในลิสต์มาก่อนถึงจะ copy ได้ใช่ป่ะ?
(ลิสต์มันเก็บแบบนั้นเปล่า?) มีวิธีให้ไม่ต้องวิ่งป่ะ? แบบ อยากได้เช่น input[3:] เหมือนเป็น pointer ไปเริ่มที่ 3 เลย
เดี๋ยวเขียนของ ML ก่อง
ผมไปดูในโค้ด C มาแล้วได้ความว่า list คือ array ที่ขยายขนาดได้ด้วยตัวเอง slice จะกระโดดไปที่ตำแหน่งเริ่มต้นแล้วค่อย copy ทีละตัว แปลว่าเขียนแบบข้างบนก็ใช้ได้
O(n)เหมือนกันแต่เขียน recursion แบบนี้มันทำ tail recursion ไม่ได้นี่นา....
ไว้ไปทำงานก่อนเดี๋ยวมาเขียนใหม่ครับ
(เขียนเป็นแต่ใน ML... เดี๋ยวไปลองหัด Haskell ก่อน รู้สึกจะเขียนเหมือน ๆ กัน)
(เวลา post เขียนเว้นย่อหน้ากันไงอ่ะครับ... ผมใช้ nbsp... แล้วมันยาวมากเลยครับ)
http://www.codenone.com/node/20
ขอดูแบบ ML บ้างครับ
ถ้าเขียนด้วย ML จะยาวหน่อย เพราะว่าตรงกระโดดข้าม c ตัว ผมไม่รู้ว่ามีฟังก์ชันหรือเปล่า เลยเขียน skiphead เอามากระโดด มันจะอ่านเอาหัว c ตัวมา แล้วคืนคู่ลำดับของหัว แล้วก็หางที่เหลือ
fun skiphead([],c) = ([],[]) | skiphead(list,0) = ([],list) | skiphead(x::xs,c) = let val (h,r) = skiphead(xs,c-1) in (x::h,r) end fun sep([],n) = [] | sep(list,n) = let val (h,rest) = skiphead(list,n) in h::sep(rest,n) end(สังเกตว่าฟังก์ชันนี้ทำงานกับลิสต์ความยาว n ในเวลา O(n))
เดี๋ยวไปเขียน version ที่เป็น tail recursion ด้วย อิอิ หนุกๆ (แต่มาอยู่ใน forum python ได้เปล่าเนี่ยะ?)
มาป่วนใน python ด้วย
ลองเขียนเป็น haskell หน้าตาออกมาเหมือนอาจารย์มะนาวเลย
(ไม่ได้ลอกนะ บังเอิญ)
haskell มี function ที่ชื่อ splitAt
หน้าตาเหมือน skiphead ของอาจารย์มะนาวเลย
เลยเอามาช่วย
part :: [a] -> Int -> [[a]] part [] _ = [] part xs size = hs : part rest size where (hs, rest) = splitAt size xsอัดเจ้ย เหมือนกันเลย....
แต่ดูแล้วชอบ where นะครับ.... ดูอ่านง่ายกว่า let ... in ... end
จริงๆ แล้วผมก็อ่านไม่ค่อยรู้เรื่องทั้งคู่ แต่รู้สึกมีหวังที่จะอ่าน ML รู้เรื่องมากกว่าอะครับ Haskell พยายามอ่านหลายรอบแล้ว ก็เศร้าๆ เหมือนเดิม
lew : เอาเวอร์ชั่นโรคจิตแบบไม่ใช้ lambda แล้วกัน เดี๋ยวมัน deprecate
ใช้lambdaแล้ว deprecate ตั้งแต่ Python versionไหนครับ
แล้ว deprecate ทุกแบบของ lambda เลยหรือเปล่า
(คือไม่ค่อยได้ติดตามข่าว CPython น่ะครับ)
ตกลงว่า lambda จะยังอยู่เหมือนเดิมนี่ครับ ตอนแรก GvR ว่าจะเอาออกโดยหาทางเลือกอื่นที่ดีกว่า แต่สุดท้ายก็หาไม่เจอ เลยสรุปว่ามันดีที่สุดแล้ว ก็เก็บไว้ ใน Py3K ก็จะยังมี
ไปไล่อ่านบล็อกของ GvR อีกรอบ มันกลับมาแล้วจริงๆ แฮะ ตกไปได้ไงเนี่ย
เห็น Ruby เค้าวัดความเร็วกันเลยวัดบ้าง #1-#4 อยู่ที่หน้านี้ส่วน #5 อยู่ที่โจทย์
ผลออกมาทำนองเดียวกัน แสดงว่าการสร้าง การก๊อปปี้ มีผลมากเหมือนกันนะเนี่ย ดูๆ ไป inline for นี่มันทำออกมาดีกว่า for ปกติซะอีก