ถามการบ้านรอบสองครับ

  • warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 1005 is not allowed to access /tmp owned by uid 0 in /var/www/sites/sugree/codenone.com/subdomains/www/html/includes/file.inc on line 190.
  • warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 1005 is not allowed to access /tmp owned by uid 0 in /var/www/sites/sugree/codenone.com/subdomains/www/html/includes/file.inc on line 190.

เป็นการวาดรูปครับซึ่งผมลองวาดดูแล้วแต่มันออกมาไม่ถูกต้องครับ รบกวนช่วยอธิบายเพิ่มเติมให้หน่อยครับว่าต้องทำเป็น Array แบบไหนจึงจะให้ผลลัพธ์ออกมาถูกต้องครับ

>
x = 5 จะต้องได้
   *****
       *  
   *** *  
   *   *
   *****
 
x = 3 จะต้องได้
   ***
     *
   *** 
 
x = 6  จะต้องได้้
   ******
        *
   **** *
   *  * *
   *    *
   ******
</blockcode> 
 
นี่เป็น Code ที่ผมลองเขียนครับแต่ผลลัพธ์ออกมาผิดครับ 
 
<blockcode [type="ruby"]>
def  draw22(n)
  n.times do |i|
    n.times do |j|
      if (i == 0 or  j == n-1 or  i  == n-1) or
         (i  == 2 and  j == 0) or 
         (i  == 2 and  j == 1) or 
         (i  == 2 and  j == 2) or
         (i  == 3 and  j == 0)
          print "*" 
      else
          print" " 
      end	    				 
    end
    print"\n"
   end
end
 
draw22(5)
draw22(3)
draw22(6)
</blockcode> 
  ช่วยเฉลยและอธิบายให้หน่อยนะครับ ว่าหากทำเป็น arr ต้องทำยังไงครับ ขอบคุณมากครับ
 
taiko_gogo's picture

นิหน่อย : เวลา แปะ code ถ้าใช้ blockcode จะทำให้code มันดูดีกว่านี้นะ

งงครับ อยากวาดอะไรหรอ?

ขออภัยครับรีบไปหน่อย ปรับcode ให้แล้วครับขออภัยจริง ๆ รบกวนช่วยแนะนำด้วยนะครับ ขอบคุณมากครับ

taiko_gogo's picture

ทำยังไง(ฟะ)เนี่ย
นี่มันคือ การ resize ใช่ไหม
คำถามแรกคือ อันไหนคือ รูปพื้นฐาน
ที่ผมเคยเขียนเล่น ๆ คือผมมีรูปพื้นฐานอยู่
แล้วเขียนให้ resize แบบขยายเอา
ไม่รู้ว่าอันนี้
ที่ผมเคยเขียนจะเป็นประโยชน์กับคุณzololong ไหม

ถ้าตามโจทย์ที่คุณzololongให้มา แล้ว x=3 เป็นรูปพื้นฐาน
ผมงงว่า พอขยายแล้วทำไมมันถึงได้แบบนั้น
หรือถ้า โจทย์ที่คุณ zololong ให้มา มี x=6 เป็นรูปพื้นฐาน
ผมก็นึก algorithm ในการ resize แบบลดขนาดไม่ออกแฮะ
ไม่รู้ว่าจะเอาอะไรมาตัดสินว่าจะตัดจุด (*) ไหนออกไปดี
ต้องให้พี่ ๆ คนอื่นช่วยซะแล้วแบบนี้ >_<

sugree's picture

มันคือ recursive มั๊ง แหม ข้อนี้เห็นแล้วคิดถึงอดีต

taiko_gogo's picture

คิดถึงอดีตแปลว่าเคยทำมาแว้ว
พี่ sugree เฉลยที :D

sugree's picture

ลืมไปแล้ว เขียนตั้งแต่สมัย pascal โน่น ต้องคิดใหม่

taiko_gogo's picture

อ๋ออออออ โอเค เก็ตแว้ว
ขอบคุณพี่sugree ครับ บอก recursiveแล้วใช่เลย
วนเป็นแบบก้นหอย
โอ้ว ข้าน้อยปัญญาน้อยนิดขอคารวะ
เดี๋ยวไปคิดก่อน

เห็นบางคน เขาเรียก snail-shell
http://channel8.msdn.com/Posts/Walking-a-multi-dimensional-array-in-the-...

taiko_gogo's picture

กำลังคิด งุงิงุงิ
ที่ผมเขียนคงดูอุบาทแหง ๆ เลย

taiko_gogo's picture

ทำได้แว้วววว เย้ มึนอยู่ตั้งนาน code ตัวเองดูหดหู่ยังไงก็ไม่รู้ซิ T_T

class RecursiveCircle
  attr_accessor :box_length,:circle,:direction
  def initialize(n)
    @box_length = n
    @circle=[]
    (@box_length+1).times do 
      @circle.push Array.new(@box_length+1," ")
    end
    @direction="r"
  end
  def draw()
    fill(0,0,0,0,@direction)
    @circle.reverse.each do |row| 
      row.each do |col|
        print col
      end
      puts ""
    end
  end
  def fill(top_offset,right_offset,bottom_offset,left_offset,direction)
    return if top_offset > @box_length/2
    if(direction=="r")
      row_index= @box_length - bottom_offset
      col_index= left_offset
      col_index.upto(@box_length -right_offset) do
        @circle[row_index][col_index]="*"
        col_index=col_index+1
      end
      fill(top_offset+1,right_offset,bottom_offset+1,left_offset,"u")
    elsif(direction=="u")
      col_index = @box_length - right_offset
      row_index = @box_length - bottom_offset
      row_index.downto(top_offset) do
        @circle[row_index][col_index]="*"
        row_index=row_index-1
      end
      fill(top_offset,right_offset+1,bottom_offset,left_offset+1,"l")
    elsif(direction=="l")
      row_index= top_offset
      col_index= @box_length - right_offset
      col_index.downto(left_offset) do
        @circle[row_index][col_index]="*"
        col_index =col_index-1
      end
      fill(top_offset+1,right_offset,bottom_offset+1,left_offset,"d")
    elsif(direction=="d")
      col_index = left_offset
      row_index = top_offset
      row_index.upto(@box_length-bottom_offset) do  
        @circle[row_index][col_index]="*"
        row_index = row_index +1
      end
      fill(top_offset,right_offset+1,bottom_offset,left_offset+1,"r")
    end
  end
end
# เวลาเอาไปใช้ก็
x = RecursiveCircle(5)
x.draw

โอยปวดคอ สนุกดีทำข้อนี้ ตอนแรกมึนอยู่นานมาก
ขอบคุณพี่sugree ที่บอกว่าเป็น recursive ไม่งั้นผมคงดูไม่ออก
แต่ถึงบอกว่าเป็น recursive คนไม่ได้เรื่องalgo อย่างผมก็นั่งดู
อยู่นานเหมือนกันว่าจะ recursive ยังไงหว่า วู๊ว อ่อนจริง ๆ(ว่าตัวเอง)
ที่ผมทำรูปมันจะต่างกับอันข้างบนหน่อยนึง จากรูปข้างบน ตอนวน
รอบแรก (ตรงขอบอ่ะ) เส้นที่ 1 กับเส้นที่ 2 มันต้องติดกัน ไม่ใช่หรอ
ผมซื่อไปหน่อย ไปคิดว่ามันไม่ติดอย่างที่เห็น นั่งงมอยู่นาน จะ recursiveไง
ให้ได้อย่างงั้นว๊า ลองเอาไปสั่งให้มัน output ดูละกันเน้อ
คราวนี้อธิบายไอเดีย
ไอเดียก็ไม่ยาก อาศัยการดูความห่างจากขอบเป็นหลัก
ลองนั่งสมาธิไปเรื่อย ๆ จะเห็นเป็นรูปน้องอ้อยลอยมา เอ้ย ไม่ใช่
พิจารณาที่ x=5 ที่มีขนาด ความกว้างสูงสุด =6 จะพบว่า การวนมันมีลักษณะคือ
( o แทนช่องว่าง , x แทนเส้นที่ลาก + แทนจุดที่จะลากต่อ เน้อ)
-กวาดไปทางขวาทีแรก ไม่ห่างจากขอบเลย
xxxxxx
ooooo+
ooooo+
ooooo+
ooooo+
oooooo
จะเห็นว่าเส้นที่จะวาดต่อ จะห่างจากขอบบน 1 ช่อง
และจะห่างจากขอบล่าง 1ช่อง
-ต่อมา การเส้นลากไปด้านล่าง
xxxxxx
ooooox
ooooox
ooooox
o++++x
oooooo
จะเห็นว่า เส้นที่จะวาดต่อ ห่างจากขอบซ้าย 1 ช่อง และขอบขวา 1 ช่อง
-ต่อมา ลากเส้นไปทางซ้าย เส้นนั้นจะห่างจากขอบทางซ้าย 1 ช่อง ขอบทางขวา 1ช่อง ขอบ
ข้างล่าง 1 ช่อง
xxxxxx
ooooox
o+ooox
o+ooox
oxxxxx
oooooo
จะเห็นว่า เส้นที่จะวาดต่อ อยู่ห่างจากขอบ บน 2 ช่อง ขอบล่าง 2 ช่อง
-ต่อมาลากเส้นขึ้น เส้นนั้นจะห่างจากขอบทางซ้าย 1 ช่อง ขอบข้างล่าง 2ช่อง และขอบ
ด้านบนอีก
xxxxxx
ooooox
ox++ox
oxooox
oxxxxx
oooooo
จะเห็นว่าเส้นที่จะวาดต่อ ห่างจากขอบซ้าย 2 ช่อง และขอบขวา 2ช่อง

อะไรทำนองนี้ จากตรงนี้เราก็จะเห็นแล้วว่าจะ recursive ยังไง
ต่อมาที่ต้องเคลียร์ให้ได้คือ จะหยุด recursive ตอนไหน
อันนี้สังเกตนิดนึงก็พอจะเดาออกว่า จะหยุด เมื่อ ความห่างจากขอบ
มีค่ามากกว่า ความกว้าง(หรือสูง)/2
พอได้ไอเดียตรงนี้แล้วก็เอาไปเขียนต่อได้ สบายแฮ
ออ จากโจทย์ ผมใช้ n แทนความสูงของวง เพราะฉนั้นตอน
สร้าง array ที่เอาไว้เก็บ เลยสร้างเป็น array ขนาด n+1
แล้วก็ code ข้างบนนี้ ตอนทำผมวนจาก ล่างขึ้นบน
ก่อนผมสั่งprint เลยต้อง reverse ก่อนเพื่อให้ได้รูปตามโจทย์

หวังว่าผมจะไม่เขียนให้งงน๊ะครับ :D
นอนหลับแล้ววันนี้ ฮิ้วว

taiko_gogo's picture

รู้สึกอนาถไอเดียตัวเอง ทำไมต้อง recursive แบบมีทิศด้วยฟระ(ฮา)
ดูจากอันที่พี่ป๊อกแปะ link ไว้แล้ว เค้า iterate ที่นึง ทั้งสี่ทิศเลย
แล้วค่อย recursive ผมเล่น recursiveเป็นทิศ ๆ เอา -_-"
ว้อววว โชว์นูบอีกแล้วอ๊ะ

taiko_gogo's picture

โทษทีครับ พิมพ์ตกอ๊ะ เอาไปใช้แบบนี้เน้อ

x = RecursiveCircle.new(5)
x.draw

มันมี recursive อีกแบบด้วยนะ
ถ้ามองที่ N = 8

********
       *
****** *
*    * *
* *  * *
* **** *
*      *
********

จะเห็นว่ามี N=6 วางซ้อนแบบกลับหัวอยู่

******
     *
**** *
*  * *
*    *
******

ส่วน N=6 ก็จะเห็นว่ามี N=4 วางซ้อนอยู่เช่นเดียวกัน

****
   *
*  *
****

กรณี 3,5,7,... ก็เช่นกันครับพี่ pok
ผมแยกได้เป็นสอง แบบ มี เลขคู่ 2,4,6,... กับเลขคี่ 3,5,7,...

 f 1 = *
 f 2 = **
        *
 f 3 = ***
         *
       ***
 f n = (วาดบรรทัดบน n ตัว)+(ข้างขวาลงมาอีก n-1ตัว)+(ด้านล่างนับจากขวาอีก 1 ตัว)+
       (วาด leftRotate(180 องฮา,f(n-2)) ลงที่ตำแหน่ง ล่างซ้าย)

ได้คร่าวๆประมาณนี้ เดี๋ยวกลับบ้านจะไปลองกับ haskell ดู

เอาโค้ด javascript ไปก่อนแล้วกันครับผม

<script language="javascript">
function solve() {
	var num = parseInt(document.getElementById("num").value);
 
	output = document.getElementById("output");
	outputArr =	f(num);
	output.innerHTML = '';
	for (i = 0; i < num; ++i) {
		for (j = 0; j < num; ++j)
			output.innerHTML += outputArr[i][j];
		output.innerHTML+='\n';
	}
 
}
function rotate2Left(a) {
	var tmp = new Array(a.length);
	for (i = 0; i < a.length; ++i) {
		tmp[i] = new Array(a.length);
		for (j = 0; j < a.length; ++j) {
			tmp[i][j] = ' ';
		}
	}
	var count = 0;
	for (i = 0,k = a.length - 1; i < a.length; ++i,k--) {
		for (j = 0,l = a.length - 1; j < a.length; ++j,l--) {
			tmp[k][l] = a[i][j] ;
		}
	}
	return tmp;
}
function f(n) {
	var arr = new Array(n);
	for (i = 0; i < n; ++i) {
		arr[i] = new Array(n);
		for (j = 0; j < n; ++j)
			arr[i][j] = ' ';
	}	
	switch(n) {
		case 1: 
			arr[0][0] = '*';
		break;
		case 2:
			arr[0][0] = '*';
			arr[0][1] = '*';
			arr[1][1] = '*';
		break;
		case 3:
			arr[0][0] = '*';
			arr[0][1] = '*';
			arr[0][2] = '*';
			arr[1][2] = '*';
			arr[2][2] = '*';
			arr[2][1] = '*';
			arr[2][0] = '*';
		break;
		default:
			for (i = 0; i < n; i++) arr[0][i] = '*';
			for (i = 1; i < n; i++) arr[i][n-1] = '*';
			arr[n-1][n-2] = '*';
			arr2 = rotate2Left(f(n-2));
			for (i = arr2.length-1,k=arr.length-1; i >=0;i--,k--) {
				for (j=0,l=0;j < arr2.length; j++,l++) {
					arr[k][l] = arr2[i][j];
				}
			}
		break;
	}
	return arr;
}
</script>
<input type="text" id="num">
<input type="button" onclick="solve()" value="solve">
<div>
	<pre id="output"></pre>
</div>

ผมก็ว่าจะลอง haskell อยู่เหมือนกัน

ลอง haskell บ้าง

เริ่มด้วยรูปทรงพื้นฐาน (ตัว C กลับด้าน)

-- base 3 = ["***",
--           "  *",
--           "***"]
--
-- base 4 = ["****",
--           "   *",
--           "   *",
--           "****"]
--
-- for n = 4
--   hbar = "****"
--   rbar = "   *"
--
base n = [hbar] ++ (replicate (n-2) rbar) ++ [hbar]
       where hbar =  replicate n     '*'
             rbar = (replicate (n-1) ' ') ++ ['*']

ต่อด้วย function ปรับขนาด dimension ด้วยการแปะ space
วัตถุประสงค์ก็คือเพื่อให้สะดวกต่อการวางรูปซ้อนกัน

-- patch (base 3) 5 = ["     ",
--                     "     ",
--                     "***  ",
--                     "  *  ",
--                     "***  "]
--
patch xs n = replicate diff blankline ++ 
             [ x ++ (replicate diff ' ')  | x <- xs]
      where blankline = replicate n ' '
            diff      = n - (length xs)

function ถัดไป ก็คือการวงรูป operlap กัน

--      ["****",        ["    ",      ["****",
--       "   *",  over   "*** ",  =>   "****",
--       "   *",         "*   ",       "*  *",
--       "****"]         "*** "]       "****"]
over xs ys = zipWith over' xs ys
           where over' linex liney = zipWith over'' linex liney
                 over'' x y | x == ' '  = y
                            | otherwise = x

อีกอันที่จำเป็นก็คือ การพลิกรูป ซึ่งเราต้องทำทั้งแนวตั้งและแนวนอน

--
--render $ flip_horizontal $ pic 4
--
--  "****"
--  "*   "
--  "*  *"
--  "****"
flip_vertical   = reverse
flip_horizontal = map reverse
flip_all        = flip_vertical . flip_horizontal

สุดท้ายก็ define รูปของเราได้

-- pic 3 is the smallest 
-- pic 4 is special case
-- pic n is overlap pic between base n and pic (n-2)
pic 3 = base 3
pic 4 = ["****","   *","*  *","****"]
pic n = (patch (flip_all $ pic (n-2)) n) `over` (base n)

ทดลอง render ด้วย function นี้

render p = do mapM print p

ทดลองเรียก

*Main> mapM (render . pic) [3..8]
"***"
"  *"
"***"
"****"
"   *"
"*  *"
"****"
"*****"
"    *"
"*** *"
"*   *"
"*****"
"******"
"     *"
"**** *"
"*  * *"
"*    *"
"******"
"*******"
"      *"
"***** *"
"*   * *"
"* *** *"
"*     *"
"*******"
"********"
"       *"
"****** *"
"*    * *"
"* *  * *"
"* **** *"
"*      *"
"********"

คัว function pic เขียนผิดไปหน่อย
จริงๆแล้วมันเป็นอย่างนี้ได้เลย

pic 1 = ["*"]
pic 2 = ["**"," *"]
pic n = (patch (flip_all $ pic (n-2)) n) `over` (base n)

ตามอ่านมาจากบลอกอีกทีครับ ชอบแนวคิดนี้มากครับ เลยอยากลองเขียนด้วยไพธอนดู แต่เนื่องจากคอมเมนต์ในบลอกพี่ป้อกไฮไลท์ไม่ได้ จึงเข้ามาตอบในนี้ครับ

#!/usr/bin/python
 
from numpy import *
def snail2(n) :
 
	# Initialize (n == 1)
	if n%2 :
		sn = [ones((1,1))]
	# Initialize (n == 2)
	else :
		sn = [ones((2,2))]
		sn[0][1][0] = 0
 
	for i in range(1,(n+1)/2):
		# Create new snail with (n+2)*(n+2) : n == dimension of previous snail
		new_sn = ones((sn[-1].shape[0]+2, sn[-1].shape[0]+2))
		# This position is always 0
		new_sn[1,0] = 0
		# Map negation of previous snail in the middle of new snail
		new_sn[1:-1,1:-1] = 1*(sn[-1] == 0)
		sn.append(new_sn)
 
	# Convert array to string
	snstr = ''
	for i,j  in zip(sn[-1].reshape(n**2),range(n**2)):
		if j%n == 0 : snstr += '\n'
		if i == 1 : snstr += '*'
		else : snstr += ' '
 
	return snstr
 
for i in range(1,9) :
	print snail2(i)

แนวคิดเหมือนกันทุกอย่างครับ เพียงแต่ใช้ numpy แทน

ถ้าเดา code ไม่ผิด
นี่ bow คิดกลับทางกับคนอื่นอีกแล้วไช่เปล่า
แทนที่จะ recursive จากใหญ่ไปเล็ก
ของ bow นี่เริ่ม build จากรูปเล็กไปรูปใหญ่

negative thinking จริงๆด้วย

veer's picture

โจทย์ข้อนี้เขาบอกขนาดใหญ่สุดไม่ใช่เหรอ นั่งวาดใน text editor เลย if ... p print :-P
---
http://blog.vee-u.com/

ขอบคุณมากครับ พี่ ๆทุกคนมากครับ T_T ทำมัยผมถึงได้คิดอะไรไม่ออก

งงโจทย์อยู่นานครับ พอพี่ป้อกบอก snail-shell ถึงได้เข้าใจ

ผมทำในแบบที่ผมถนัดครับ คือ numpy + array slicing

#!/usr/bin/python
 
from numpy import *
 
def snail(n):
	if n < 3 : raise ValueError, 'snail(n) : n must greater be than 3'
	sn = ones((n,n))
	sn[1,:n-1] = 0
	for i in range(1,n-2) :
		if i%4 == 0 :
			sn[i/2+1,i/2-1:i/2-1+(n-i)] = 0
		elif i%4 == 1 :
			sn[(i+1)/2:(i+1)/2+(n-i-1),n-(i+3)/2] = 0
		elif i%4 == 2 :
			sn[n-i/2-1,i/2:i/2+(n-i)] = 0
		else :
			sn[(i+3)/2:(i+3)/2+(n-i-1),(i-1)/2] = 0
	if n%2 == 0 : sn[n/2,n/2-1] = 0
	snstr = ''
	for i,j  in zip(sn.reshape(n**2),range(n**2)):
		if j%n == 0 : snstr += '\n'
		if i == 1 : snstr += '*'
		else : snstr += ' '
	return snstr
 
print snail(32)

update อธิบายเพิ่มครับ เพราะเจ้าของกระทู้ให้สอนการบ้าน ไม่ได้ให้เฉลยการบ้าน

หลักการคือ แทนที่จะเริ่มด้วยพื้นที่ว่าง ก็เริ่มด้วยรูปดาวก่อน โดยการสร้าง array ขนาด n*n สมาชิกทุกตัวมีค่าเป็น 1 (บรรทัด sn = ones((n,n))) แล้วมาพิจรณาว่า position ไหนของ array ควรจะเป็น 0 บ้าง (ซึ่งยากตรงนี้) หากได้แล้ว ก็แทนค่า array ที่เป็น 1 ด้วยดาว 0 ด้วยพื้นที่ว่าง

การหา position ของ array ที่เป็น 0 แยกได้เป็น 4 กรณีใหญ่ ๆ คือ บน => ขวา => ล่าง => ซ้าย วนไปเรื่อย ๆ เลยใช้ modulo 4 ใน การแยก 4 กรณีใหญ่ ๆ ซึ่งต้องวนลูปทั้งหมด n-2 ครั้ง แต่กรณีแรก เหมือนกันหมดไม่ว่า n มีขนาดเท่าไร เลยมีบรรทันนี้ sn[1,:n-1] = 0

ที่เหลือก็นั่งคิดเลขเอาครับ ว่าพอเป็นกรณีที่ 1 (บน) ต้องแทนค่าด้วยศูนย์ row ไหน จาก column ไหนถึง column ไหน กรณีที่ 2 (ขวา) ต้องแทนค่าด้วยศูนย์ column ไหน จาก row ไหนถึง row ไหน ไปเรื่อย ๆ

แล้วก็ในกรณี n เป็นเลขคู่จะมีเลขศูนย์เพิ่มขึ้นมาหนึ่งตัว ตรงกลาง เลยต้องมีบรรทัดนี้ if n%2 == 0 : sn[n/2,n/2-1] = 0

ส่วนบรรทัดที่เหลือก็แปลง หนึ่งเป็นดาว ศูนย์เป็นพื้นที่ว่างครับ

taiko_gogo's picture

โอ้ว สุดยอด ผมชอบไอเดียนี้อ่ะ >_<

เห็นพวกนี้แล้วจะเป็นลม
sn[(i+1)/2:(i+1)/2+(n-i-1),n-(i+3)/2]

อีกอย่าง คิดกลับทางแบบนี้ ถือว่าเป็นพวก negative thinking :)

เหอ ๆๆๆ พี่ป้อกนี่ดูคนจากโค้ดได้เก่งจริง ๆ ครับ :D

ลองเขียนแบบมองในมุมมองของหอยทากดู (หอยทากที่เดินเป็นวงหอย) แนวคิดคือแปลงข้อมูลให้มาอยู่ในรูปของ path ก่อน

เช่นหากขนาดของตารางเป็น 5 หอยทากจะเดินไปในทิศทาง rrrrddddlllluurrx (ขวา ล่าง ซ้าย บน ขวา และหยุดกินใบไม้)

>
#!/usr/bin/python
 
# This is our hero!
class snail():
 
    def __init__(self):
        self.trace = ''
        self.travelledDistance = 0
 
    def walk(self, distance, direction):
        # check input
        if distance == 0:
            self.trace = self.trace + 'x'   # if there's no distance, do eat
        elif distance < 0:
            return
        # always use lowercase
        direction = direction.lower()
        if direction == 'up':
            self.trace = self.trace + 'u' * distance
        elif direction == 'down':
            self.trace = self.trace + 'd' * distance
        elif direction == 'left':
            self.trace = self.trace + 'l' * distance
        elif direction == 'right':
            self.trace = self.trace + 'r' * distance
        else:
            return
        self.travelledLen = self.travelledDistance + distance
 
    def doHelix(self, distance, dir = ['right', 'down', 'left', 'up']):
        if distance < 0:
            return
        compass = 0
        self.walk(distance, dir[compass % 4])
        compass = compass + 1
        for step in range(distance, -1, -2):
            self.walk(step, dir[compass % 4])
            compass = compass + 1
            self.walk(step, dir[compass % 4])
            compass = compass + 1
</blockcode>
 
แล้วจากนั้นก็เอา path ที่ได้ไป plot โดยเริ่มจากจุด 0,0 ถ้าหากหอยเดินตกขอบที่กำหนดเราไม่สนใจ
 
<blockcode [type="python"]>
# Plot the trace in n*n sheet
def plot(trace, n):
    sheet = {}
 
    # Firstly, observe the trace and plot
    i = 0
    j = 0
    for step in range(0, len(trace)):
        if trace[step] == 'u':
            sheet[(i, j)] = step + 1
            i = i - 1
        elif trace[step] == 'd':
            sheet[(i, j)] = step + 1
            i = i + 1
        elif trace[step] == 'l':
            sheet[(i, j)] = step + 1
            j = j - 1
        elif trace[step] == 'r':
            sheet[(i, j)] = step + 1
            j = j + 1
        elif trace[step] == 'x': 
            sheet[(i, j)] = step + 1
 
    # Secondly, print the plot
    for i in range(0, n):
        for j in range(0, n):
            if sheet.has_key((i, j)):
                print '*',
            else:
                print ' ',
        print ''
</blockcode>
 
ลองพล็อตดูโดยเรียกใช้ตามนี้
 
<blockcode [type="python"]>
for n in range(0, 6):
    s = snail.snail()
    s.doHelix(n)
    s.trace
    snail.plot(s.trace, n + 1)
</blockcode>
 
ก็จะได้
 
<blockcode>
'xxx'
* 
'rdl'
* * 
  * 
'rrddllxx'
* * * 
    * 
* * * 
'rrrdddlllur'
* * * * 
      * 
*     * 
* * * * 
'rrrrddddlllluurrxx'
* * * * * 
        * 
* * *   * 
*       * 
* * * * * 
'rrrrrdddddllllluuurrrdl'
* * * * * * 
          * 
* * * *   * 
*     *   * 
*         * 
* * * * * * 
</blockcode>
 
code ยาวแฮะ ไม่เหมาะกับเขียนในห้องสอบอย่างแรง

โค้ดเข้าใจง่ายดีครับ

ผมว่าโจทย์มันยากเกินกว่าจะเป็นข้อสอบได้อยู่แล้วครับ

ขอบคุณครับ แต่พึ่งเห็นว่าผมมีแอบปล่อยบั๊กเล็กๆด้วย แหะๆ

>
self.travelledLen = self.travelledDistance + distance
</blockcode>
 
ต้องเป็น
 
<blockcode [type="python"]>
self.travelledDistance = self.travelledDistance + distance
</blockcode>
 
เกิดจากตอนเปลี่ยนชื่อตัวแปรแล้วเปลี่ยนไม่หมด ดีนะที่ไม่ได้เรียกใช้ค่านี้

แบ่ง abstraction ได้สวยดี
ทำให้ code อ่านง่าย

มีใครทำแบบไม่ต้อง allocate array มาก่อนบ้างได้ไหมครับ?

โห..วิธีเพียบเลยครับ แต่ข้อ 3 กับ ข้่อ 4 จากกระทู้ ช่วยสอนการบ้านหน่อยครับ ยังไม่ได้เฉลยและอธิบายเลยครับ รบกวนด้วยครับ ขอบคุณมากครับ

ย้าย Codenone

ประกาศย้าย Codenone ไปใช้ Forum ของ Blognone แทนครับ ตามไปตั้งกระทู้ต่อได้ที่ Codenone Forum (รายละเอียดอ่านจากกระทู้ ย้าย Codenone ไปรวมกับ Blognone)

กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น