Just algorithm!
Alien Numbers



ไม่ได้เขียน blog มานานมาก

แต่ว่าตอนนี้มีองค์ประกอบดีๆ 3 อย่างคือ

1. เพิ่งพลาดไม่ได้ join codejam เลยต้องฝึกฝีมือเผื่อปีหน้า

2. กำลังหัดเขียน f#

3. ช่วงนี้งานค่อนข้างโอเค ไม่ยุ่งมาก



เลยตั้งเป้าว่า solve codejam ไปเรื่อย ๆ ด้วย f# และเขียน blog ไปด้วย



เริ่มที่ข้อแรก Alien Numbers

โจทย์คือ จะมีตัวเลขภาษาต่างดาวมา 2 ชุด ให้แปลจากตัวเลขภาษานึงไปอีกภาษานึง



สมมติมนุษย์ใช้เลขอารบิก 0123456789 มนุษย์ต่างดาวใช้เลข hex 0123456789abcdef

ดังนั้นเลข 10 จะเท่ากับ a



มนุษย์ต่างดาวไม่ได้ใช้ภาษาเหมือนเรา 0-9 ของเขาอาจจะเป็น )!@#$%^&*(

แต่หลักการนับเหมือนเลขของมนุษย์ทุกอย่าง

อ่านรายละเอียดเพิ่ม ที่นี่ครับ



โจทย์ข้อนี้ถือว่าง่ายมาก ถ้ารู้จักเลขฐานก็สบายเลย

วิธีคิดคือให้แปลจากภาษาแรกเป็น int ก่อน แล้วจาก int ค่อยแปลเป็นภาษาที่สอง



เริ่มจาก function หลัก

let solve value txt1 txt2 =

function ชื่อ solve

value คือ เลขที่ต้องแปล เช่น foo

txt1 คือ ชุดตัวเลขของเลขที่ต้องแปล เช่น of8

txt2 คือ ชุดตัวเลขอีกภาษานึง ที่เราต้องการแปลเป็นภาษานี้ เช่น 0123456789

value type เป็น string ส่วน txt1 กับ txt2 เป็น char[]



function การแปลจาก txt1 เป็น int คือ

let txtToNum txt v =
    let baseN = Array.length txt
    let foldFn a b = a * baseN + Array.IndexOf(txt, b)
    Seq.fold foldFn 0 v

baseN คือ จำนวนเลขฐาน เช่น of8 เป็นเลขฐาน 3

foldFn คือ สูตรการคำนวนเลขฐานอื่นๆ เป็น int

โดยเอาเลขก่อนหน้า (a) x เลขฐาน (baseN) + ค่าของตัวอักษรนั้น



เช่นเลข foo จาก of8

โดยถ้านับตามตำแหน่ง f เท่ากับ 1 ส่วน o เท่ากับ 0

f = 1

fo = 1 * 3 + 0 = 3

foo = 3 * 3 + 0 = 9

ดังนั้น foo = 9



function การแปลจาก int เป็น txt2 คือ

let numToTxt txt v =
    let baseN = Array.length txt
    let unfoldFn = function
        | -1 -> None
        | n  -> match Math.DivRem(n, baseN) with
                | 0, r -> Some(r, -1)
                | d, r -> Some(r, d)
    v |> Seq.unfold unfoldFn
      |> Enumerable.Reverse
      |> Seq.map (Array.get txt)
      |> Seq.map string
      |> String.Concat

unfoldFn คือ function แปลเลข int เป็นเลขฐานใด ๆ

สมมติเป็นเลข 454 และต้องการแปลเป็นเลขฐาน 6



454 / 6 ได้ 75 เศษ 4

75 / 6 ได้ 12 เศษ 3

12 / 6 ได้ 2 เศษ 0

2 / 6 ได้ 0 เศษ 2



เราจะได้ 4,3,0,2 ผลลัพธ์ที่ได้ต้องอ่านย้อนหลัง

เราเลยต้อง call Enumerable.Reverse เป็น 2,0,3,4

Seq.map (Array.get txt) คือการ map กับอีกชุดอักษร

เช่น 2,0,3,4 map กับ A?JM!. ก็จะกลายเป็น J,A,M,!



แล้ว Seq.map string กับ String.Concat คือ แปลงเป็น string

จาก J,A,M,! เป็น JAM!



เวลาเรียก function ก็ง่าย

value |> txtToNum txt1
      |> numToTxt txt2

โยน value เข้าไป txtToNum และเอาผลลัพธ์ไป numToTxt



จบ





Create Date : 03 พฤษภาคม 2557
Last Update : 27 พฤษภาคม 2557 12:08:33 น. 0 comments
Counter : 1196 Pageviews.

ชื่อ :
Comment :
  *ใช้ code html ตกแต่งข้อความได้เฉพาะสมาชิก
 

chaowman
Location :
กรุงเทพฯ Thailand

[Profile ทั้งหมด]

ฝากข้อความหลังไมค์
Rss Feed
Smember
ผู้ติดตามบล็อก : 8 คน [?]





New Comments
Group Blog
 
All Blogs
 
Friends' blogs
[Add chaowman's blog to your web]
Links
 

 Pantip.com | PantipMarket.com | Pantown.com | © 2004 BlogGang.com allrights reserved.