Chuyển đến nội dung
Diễn đàn CADViet
ketxu

[Hỏi]Đố vui với LISP

Các bài được khuyến nghị

Gởi bạn Detailing!

Hôm qua chúng ta có bàn đến chuyện nhanh/chậm của repeat/while, và tôi đã có vài nhận định về chúng. Đêm nằm nghĩ lại thì ngộ ra điều này:

1). Ket nói dùng while trong bài đố đó là nhanh hơn repeat (vì nếu while duyệt qua mà đạt y/c thì dừng lặp còn repeat lặp đến hết), tôi đồng ý và đưa ra ví dụ "1 lặp và 999 lặp". Hoá ra điều này quá phiêu lưu, vì ngộ nhỡ cặp sublst đó nó nằm cuối cùng thì số vòng lặp là như nhau, mà có lẽ là mỗi repeat nhanh hơn mỗi while (có ai kiểm tra giùm???) nên lúc này dùng repeat nhanh hơn. Vậy kết luận: nhanh/chậm là hên/xui chăng?

2). Câu đại ý "có khi không dùng while được mà bắt buộc phải dùng repeat" là câu tương đối thôi nhé Detailing! Ý tôi nói là trong trường hợp này dùng repeat chắc chắn nhanh hơn while chứ không phải không thể dùng while, vì với mỗi repeat thì hình như đều có thể dùng while để thay thế được. VD: "(repeat 10" thì có thể thay bằng "(setq x 0) (while (< x 10) (setq x (1+ x))" được.

Bạn nào hiểu rõ hơn thì xin chỉ giáo, đa tạ. Có loãng topic tí, mong thông cảm.

Chào bạn,

thật nhọc công bạn quá.

Vì lisp ko cho thoát khỏi hàm khi đã dc nạp (lý do mình đã giải thích ở trên) nên while hay repeat nhanh chậm mình xin thua. Nhưng với các ngôn ngữ khác mình chắc chắn vòng lặp theo số lần nhất định và thoát (break, exit for, exit do, ...) sẽ nhanh hơn hoặc bằng cái while.

while hoàn toàn có thể thay cho repeat dc. Ngoài ra trong VB còn có dạng Do..Loop Until cũng tương tự như while.

Thân!

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Mời (và nhờ) các bạn cùng tìm lỗi của bài toán sau đây:

Trong bản vẽ đính kèm có 1 cặp Spline màu đỏ và 1 cặp Line màu trắng. Với cặp màu đỏ thì chưa phát hiện ra lỗi, nhưng với cặp màu trắng thì có lỗi. Bài toán này xuất phát từ thực tế công việc, mà tôi cũng không hiểu tại sao.

Lisp y/c nhập số điểm chia, chọn đường 1 và chọn đường 2. Kết quả lisp sẽ vẽ 2 Line.

Nhưng khi nhập n=100 và n=500 thì không lỗi, còn nhập n=300 thì lỗi.

http://www.cadviet.com/upfiles/3/do_vui_ha_1.dwg

;Doan Van Ha CADViet.com
(defun C:HA ( / obj1 obj2 num lst1 lst2 p1 p2 q1 q2)
(setq num (getint "\nNhap so diem chia: "))
(setq obj1 (vlax-ename->vla-object (car (entsel "\nChon duong thu 1: ")))  lst1 (LISTP_CURVE obj1 num)
      	obj2 (vlax-ename->vla-object (car (entsel "\nChon duong thu 2: ")))  lst2 (LISTP_CURVE obj2 num)
      	p1 (car lst1) q1 (last lst2) p2 (car lst2) q2 (last lst1))
(entmake (list '(0 . "LINE") (cons 62 3) (cons 10 p1) (cons 11 q1)))
(entmake (list '(0 . "LINE") (cons 62 4) (cons 10 p2) (cons 11 q2))))
(defun LISTP_CURVE (obj num / step dis lst)	;T¹o list points of Curve.
(setq step (/ (vlax-curve-getDistAtPoint obj (vlax-curve-getEndPoint obj)) (1- num)) dis 0)
(repeat num
 (setq lst (cons (vlax-curve-getPointAtDist Obj dis) lst) dis (+ step dis)))
lst)

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Mời (và nhờ) các bạn cùng tìm lỗi của bài toán sau đây:

Trong bản vẽ đính kèm có 1 cặp Spline màu đỏ và 1 cặp Line màu trắng. Với cặp màu đỏ thì chưa phát hiện ra lỗi, nhưng với cặp màu trắng thì có lỗi. Bài toán này xuất phát từ thực tế công việc, mà tôi cũng không hiểu tại sao.

Lisp y/c nhập số điểm chia, chọn đường 1 và chọn đường 2. Kết quả lisp sẽ vẽ 2 Line.

Nhưng khi nhập n=100 và n=500 thì không lỗi, còn nhập n=300 thì lỗi.

http://www.cadviet.c...do_vui_ha_1.dwg

;Doan Van Ha CADViet.com
(defun C:HA ( / obj1 obj2 num lst1 lst2 p1 p2 q1 q2)
(setq num (getint "\nNhap so diem chia: "))
(setq obj1 (vlax-ename->vla-object (car (entsel "\nChon duong thu 1: ")))  lst1 (LISTP_CURVE obj1 num)
  		obj2 (vlax-ename->vla-object (car (entsel "\nChon duong thu 2: ")))  lst2 (LISTP_CURVE obj2 num)
  		p1 (car lst1) q1 (last lst2) p2 (car lst2) q2 (last lst1))
(entmake (list '(0 . "LINE") (cons 62 3) (cons 10 p1) (cons 11 q1)))
(entmake (list '(0 . "LINE") (cons 62 4) (cons 10 p2) (cons 11 q2))))
(defun LISTP_CURVE (obj num / step dis lst)	;T¹o list points of Curve.
(setq step (/ (vlax-curve-getDistAtPoint obj (vlax-curve-getEndPoint obj)) (1- num)) dis 0)
(repeat num
 (setq lst (cons (vlax-curve-getPointAtDist Obj dis) lst) dis (+ step dis)))
lst)

Lỗi này phát sinh khi cộng dồn : dis (+ step dis) trong hàm LISTP_CURVE.

Về lí thuyết thì sau khi lặp num lần thì dis phải bằng chiều dài của Curve, nhưng ... thực tế thì có lúc bằng lúc không bằng như bạn đã gặp với t/hợp 300.

khi dis lớn hơn chiều dài của Curve (mặc dù sai số rất nhỏ) hàm (vlax-curve-getPointAtDist Obj dis) -> nil

và đây là nguyên nhân gây ra lỗi sau đó. (bạn có thể k/tra trong k/quả trả về của hàm LISTP_CURVE)

 

Cách khắc phục : lặp num -1 lần , sau đó lấy EndPoint của Curve thêm vào danh sách.

(defun LISTP_CURVE (obj num / step dis lst)
 (setq step (/ (vlax-curve-getDistAtPoint obj (vlax-curve-getEndPoint obj)) (1- num )) dis 0)
 (repeat (1- num)
(setq lst (cons (vlax-curve-getPointAtDist Obj dis) lst)
  dis (+ step dis)))
 (setq lst (cons (vlax-curve-getEndPoint Obj) lst))
 lst)

  • Vote tăng 2

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Hết sức cám ơn bác Gia Bách!

May mà tình cờ phát hiện ra lỗi này và được bác khắc phục chứ không thì toi cả 1 phần mềm, vì đôi khi không biết nó bệnh ở bộ phận nào mà uống thuốc!

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Theo mọi người, code nào để lấy list con từ phần tử thứ n của list ngắn nhất ?

Ngắn nhất có thể hiểu theo nghĩa ít dấu ngoặc nhất hoặc ít ký tự nhất.

Hàm (list Số_INT)

 

Kết quả yêu cầu :

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 0)

(4 3 2 1 0 1 2 3 4)

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) -1)

nil

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 1)

(3 2 1 0 1 2 3 4)

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 8)

(4)

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 9)

nil

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Ngắn nhất thì chịu, nhưng hơi dài thì cũng chơi được:

(defun HA (lst sta / len1 len2 n lst1)
(setq len1 (length lst) len2 (- len1 sta) n (+ sta len2))
(if (<= 0 sta len1)
 (repeat len2
  (setq lst1 (cons (nth (setq n (1- n)) lst) lst1)))
 nil))

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Theo mọi người, code nào để lấy list con từ phần tử thứ n của list ngắn nhất ?

Ngắn nhất có thể hiểu theo nghĩa ít dấu ngoặc nhất hoặc ít ký tự nhất.

Hàm (list Số_INT)

 

Kết quả yêu cầu :

Bạn DVH viết dài quá. Tue_NV có đáp án ngắn đây, (chưa xét về tốc độ)

Nếu xét về tốc độ có lẽ nên viết hàm khác

(defun nthmem (lst n) (repeat n (setq lst (cdr lst))))

 

@DVH: Dòng (if (<= 0 sta len1)

có thể bỏ được vì Repeat n .... với n là số âm thì kết quả trả về NIL đúng với ý đồ lập trình rồi và dòng NIL ở cuối có thể bỏ được luôn

  • Vote tăng 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bác ĐVH viết logic nhưng dài quá. Bác Tuệ làm gần đúng yêu cầu bài ra, chỉ chưa xét n = 0 như kết quả yêu cầu, nên thiếu 1 ngoặc if hoặc cond nữa.

Kiểu như :

(defun NthMem (lst i)
 (if (zerop i) lst(repeat i (setq lst (cdr lst))))
)

Ngoài ra, tốc độ cdr 1 list cũng khá nhanh (không chậm như mọi người thường nghĩ đâu ạ), nên đáp án bác Tuệ đưa ra cũng chấp nhận luôn được phần tốc độ. Tks bác

 

Nhân tiện đề bài trên các bác thử làm luôn 1 đề bài khác,cách dùng cũng na ná (không xét tốc độ) :

- Remove phần tử thứ n trong 1 list.

- Yêu cầu tương tự bên trên: hàm (list n), phần tử đầu tiên mang số thứ tự 0, n <0 hoặc > length list thì trả về nil

  • Vote tăng 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bác ĐVH viết logic nhưng dài quá. Bác Tuệ làm gần đúng yêu cầu bài ra, chỉ chưa xét n = 0 như kết quả yêu cầu, nên thiếu 1 ngoặc if hoặc cond nữa.

Kiểu như :

(defun NthMem (lst i)
 (if (zerop i) lst(repeat i (setq lst (cdr lst))))
)

Ngoài ra, tốc độ cdr 1 list cũng khá nhanh (không chậm như mọi người thường nghĩ đâu ạ), nên đáp án bác Tuệ đưa ra cũng chấp nhận luôn được phần tốc độ. Tks bác

 

Nhân tiện đề bài trên các bác thử làm luôn 1 đề bài khác,cách dùng cũng na ná (không xét tốc độ) :

- Remove phần tử thứ n trong 1 list.

- Yêu cầu tương tự bên trên: hàm (list n), phần tử đầu tiên mang số thứ tự 0, n <0 hoặc > length list thì trả về nil

Ừ! Đúng là mình chưa xét n=0

Tận dụng Lisp trên, giải câu đố của Ketxu


(defun nthi (L n / nthmem)
 (defun NthMem (lst i)
  (if (zerop i) lst(repeat i (setq lst (cdr lst))))
 )
(if (< n (length L))
(append (reverse(nthmem (reverse L) (- (length L) n -1))) (NthMem L n))))

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Đây xem sao:

P/S: câu đố tiếp theo

(defun HA ( n l / i )
(setq i -1)
(if (<= 0 n (length l))
 (vl-remove-if '(lambda ( x ) (= (setq i (1+ i)) n)) l)))

  • Vote tăng 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Đây xem sao:

(defun HA ( n l / i )
(setq i -1)
(if (<= 0 n (length l))
 (vl-remove-if '(lambda ( x ) (= (setq i (1+ i)) n)) l)))

Cái này chưa đúng yêu cầu :

phần tử đầu tiên mang số thứ tự 0, n <0 hoặc > length list thì trả về nil

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bác Tue_NV xem lại xem: khi n=len_lst thì nó trả về nguyên lst, chứ của bác thì hình như không đúng ý ket.

Cái của bác không bao giờ loại được phần tử cuối cùng ra khỏi lst, đồng thời cũng không lấy được nguyên cả lst.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bác Tue_NV xem lại xem: khi n=len_lst thì nó trả về nguyên lst, chứ của bác thì hình như không đúng ý ket.

Cái của bác không bao giờ loại được phần tử cuối cùng ra khỏi lst, đồng thời cũng không lấy được nguyên cả lst.

Mình chỉ chưa xét tới n=0 thôi. Còn lại thì đúng như yêu cầu

Còn bài trích dẫn trên của ketxu thì nó ra như thế này :

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 8)

(4)

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 9)

nil

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Hình như bác vẫn chưa hiểu ý tôi, hay tôi có nhầm không hè:

1). Làm sao bác tạo lst mà phần tử cuối cùng bị remove?

2). Làm sao bác tạo lst mà các phần tử đều giữ nguyên? Theo đề bài thì khi n=9 nó sẽ trả về lst cũ, khi n>=10 nó mới nil bác ạ.

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Hình như bác vẫn chưa hiểu ý tôi, hay tôi có nhầm không hè:

1). Làm sao bác tạo lst mà phần tử cuối cùng bị remove?

2). Làm sao bác tạo lst mà các phần tử đều giữ nguyên? Theo đề bài thì khi n=9 nó sẽ trả về lst cũ, khi n>=10 nó mới nil bác ạ.

Ơ! Cái đề của Ketxu như thế này mà!!!!

 

Theo mọi người, code nào để lấy list con từ phần tử thứ n của list ngắn nhất ?

Ngắn nhất có thể hiểu theo nghĩa ít dấu ngoặc nhất hoặc ít ký tự nhất.

Hàm (list Số_INT)

 

 

Kết quả yêu cầu :

......

........

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 8)

(4)

 

Command: (nthmem '(4 3 2 1 0 1 2 3 4) 9)

nil

 

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

 

Chúng ta đang bàn câu đố sau cơ mà, chứ đâu phải câu đố đầu?

Bạn xem lại bài viết số 190 của bạn.

Bạn trả lời không trích dẫn. Ai biết bạn trả lời cho bài viết nào?

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Bạn xem lại bài viết số 190 của bạn.

Bạn trả lời không trích dẫn. Ai biết bạn trả lời cho bài viết nào?

 

Vâng, thiếu trích dẫn, nhưng câu đố sau thì bác chưa đúng!

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Đây xem sao:

P/S: câu đố tiếp theo

(defun HA ( n l / i )
(setq i -1)
(if (<= 0 n (length l))
 (vl-remove-if '(lambda ( x ) (= (setq i (1+ i)) n)) l)))

Có code này tương đương với code trên, ngắn hơn 1 chút. Tuy nhiên, cả 2 code đều xem phần tử đầu tiên là 0, phải thêm thắt 1 chút mới đúng yêu cầu của câu đố của Ketxu được


(defun nthi (L n)
 (if (<= 0 n (length L))(ACET-LIST-REMOVE-NTH n L))
)

  • Vote tăng 1

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Tks 2 bác. Yêu cầu của ketxu thực ra không nhất nhất phải chuẩn chỉ theo số lượng list hay phần tử đầu như thế nào, mà chỉ là để dẫn dắt 2 thủ thuật rất hay để làm code ngắn gọn, và rất tuyệt là các bác lần lượt xới nó lên rồi. Bravo !!

1. (repeat n (setq lst (cdr lst)))

2. (vl-remove-if '(lambda ( x ) (= (setq i (1+ i)) n)) l)

 

Ngoài ra, trong câu 1 cũng có thể sử dụng vl-member-if / vl-member-if-not thay vào đáp án của bác ĐVH.

Tks 2 bác lần nữa.

Chờ câu đố tiếp theo ^^

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Trong mặt phẳng, cho 3 điểm p1, p2, p3 tạo thành 1 tam giác đều. pt là 1 điểm nằm trong tam giác đó. Hãy lập hàm tính tổng khoảng cách từ pt đến các cạnh của tam giác, sao cho số cặp () là ít nhất, dạng hàm: FUNC(p1 p2 p3 pt).

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Trong mặt phẳng, cho 3 điểm p1, p2, p3 tạo thành 1 tam giác đều. pt là 1 điểm nằm trong tam giác đó. Hãy lập hàm tính tổng khoảng cách từ pt đến các cạnh của tam giác, sao cho số cặp () là ít nhất.

 

Nghĩa là .....???

Chia sẻ bài đăng này


Liên kết tới bài đăng
Chia sẻ trên các trang web khác

Tạo một tài khoản hoặc đăng nhập để nhận xét

Bạn cần phải là một thành viên để lại một bình luận

Tạo tài khoản

Đăng ký một tài khoản mới trong cộng đồng của chúng tôi. Điều đó dễ mà.

Đăng ký tài khoản mới

Đăng nhập

Bạn có sẵn sàng để tạo một tài khoản ? Đăng nhập tại đây.

Đăng nhập ngay

×