我现在很难过。请注意,斗争已经教会了我很多关于lisp的知识。但是,此时我可能需要一点点推动或指导。
你被给予N支,其中每根棍都是正整数长度。在棒上进行切割操作,使得它们全部减小最小棒的长度。
假设我们有6支长度
5 4 4 2 2 8 然后在一次切割操作中,我们从6根棍子中的每一根切割出长度为2的切口。对于下一次切割操作,留下4根棒(长度为非零),其长度为
3 2 2 6 重复上述步骤直到没有留下棍棒。
给定N根木棍的长度,打印在后续剪切操作中切割的木棍数量。
输入格式 第一行包含单个整数N. 下一行包含N个整数:a0,a1,... aN-1用空格分隔,其中ai表示第i个长度。
输出格式 对于每个操作,打印单独切割的棒数。
约束 1≤N≤1000 1≤ai≤1000
所以我得到的所有样本测试用例都是正确的,但其他一些我没有。例如
输入:
8
8 8 14 10 3 5 14 12
他们希望输出
8
7
6
4
3
2
但是我的代码提供了
8
7
6
4
2
这是我现在提出的功能。
(defun cut-print (numbers cut-length)
(let ((x numbers) (y cut-length) (k 0))
(loop while (> (length x) 0) do
(tagbody
;; subtracting the min value from all list elements
(setq x (map 'list (lambda (i) (- i y)) x))
;; Don't print if the list length hasn't changed
;; from last iteration
;; else save length changes and print
(cond ((= k (length x)) (go bottom))
((not (= k (length x)))
(setq k (length x))
(format t "~d~%" k)))
;; move to here if nothing is printed to
;; stdout during the current iteration
bottom
(setq x (remove-if (lambda (x) (<= x 0)) x))))))
我在俯瞰什么?根据测试用例,似乎上面的逻辑将根据其预期输出跳过切割操作。
答案 0 :(得分:3)
y
如何变化?在你的程序中,它没有改变......
风格:
一个简单的递归版本:
(defun cut (sticks)
(when sticks
(print (length sticks))
(let ((smallest (reduce #'min sticks)))
(cut (remove-if-not #'plusp
(mapcar (lambda (stick)
(- stick smallest))
sticks))))))
另一个递归版本可能如下所示:
(defun cut (sticks)
(labels ((%cut (sticks)
(when sticks
(print (length sticks))
(let ((smallest (first sticks)))
(%cut (mapcar (lambda (stick)
(- stick smallest))
(member smallest (rest sticks)
:test-not #'=)))))))
(%cut (sort sticks #'<))))
甚至:
(defun cut (sticks)
(labels ((%cut (sticks length)
(when sticks
(print length)
(let ((prefix-length (or (position (first sticks) sticks
:test-not #'=)
1)))
(%cut (nthcdr prefix-length sticks)
(- length prefix-length))))))
(setf sticks (sort sticks #'<))
(%cut sticks (length sticks))))
一个简单的LOOP版本:
(defun cut (numbers)
(loop with smallest
while numbers do
(print (length numbers))
(setf smallest (reduce #'min numbers)
numbers (loop for n in numbers
for n1 = (- n smallest)
when (plusp n1)
collect n1))))
答案 1 :(得分:3)
作为一个小型的脑筋急转弯,这是解决问题的一个较短的解决方案:
(defun sticks (&rest sticks)
(do ((rest (sort sticks #'<) (remove (car rest) rest)))
((null rest))
(print (length rest))))
编辑:我同意Rainer Joswig,但保持代码不变,以便他的评论仍然有意义。
答案 2 :(得分:1)
看起来你让事情复杂化了。为什么要使用tagbody呢?这是一个简单的Common Lisp解决方案,用于这种所谓的挑战。它通过了测试。
(defun cut (sticks)
(let ((shortest (reduce #'min sticks)))
(mapcan (lambda (x) ;; I user mapcan to not traverse list twice
(let ((res (- x shortest)))
(when (plusp res) (list res)))) sticks)))
(defun cut-the-sticks (n sticks)
(if (null sticks)
nil
(let ((cutted (cut sticks)))
(format t "~&~D" n)
(cut-the-sticks (length cutted) cutted))))
(cut-the-sticks (read)
(with-input-from-string (in (read-line))
(loop :for x = (read in nil nil)
:while x :collect x)))
答案 3 :(得分:0)
很少练习使用lisp(无法获取cons细胞)因此我将在python中提供解决方案
def cutprint(lst):
#sort the list
lst = sorted(lst)
#let the maxcut so far be the size of first stick
maxcut = lst[0]
#get the size of the list
n = len(lst)
#submit the initial size of the list
yield n
#Loop over all sticks in the list
for stick in lst:
#subtract the current max cut from the stick
stick -= maxcut
#if the cut was to little, we have done the maximum cuts possible
if stick > 0:
#Add the remainder of the last cut to maxcut
maxcut += stick
#submit the current value of n
yield n
#Since we are cutting at each iteration, subtract 1 from n
n -= 1
我认为代码非常自我解释,应该很容易理解
用法:
>>> import stick
>>> for k in stick.cutprint([2, 2, 3, 4, 5, 7, 4, 2, 3, 4, 5, 6, 7, 34]):
... print k
...
14
11
9
6
4
3
1