53 lines
1.7 KiB
Common Lisp
Executable file
53 lines
1.7 KiB
Common Lisp
Executable file
#!/bin/sh
|
|
#|-*- mode:lisp -*-|#
|
|
#|
|
|
exec ros -Q -- $0 "$@"
|
|
|#
|
|
(progn ;;init forms
|
|
(ros:ensure-asdf)
|
|
#+quicklisp(ql:quickload '() :silent t)
|
|
)
|
|
|
|
(defpackage :ros.script.subset-sum.3983202585
|
|
(:use :cl))
|
|
(in-package :ros.script.subset-sum.3983202585)
|
|
|
|
(defun ten-to-bin (x)
|
|
"Преобразует число в список бит"
|
|
(let ((bin '()))
|
|
(loop while (/= 0 x) do
|
|
(multiple-value-bind (quotient remainder) (truncate x 2)
|
|
(setf x quotient)
|
|
(push remainder bin)))
|
|
bin))
|
|
|
|
(defun calculate-sum (numbers mask)
|
|
"Считает сумму элементов, соответствующих единицам в маске."
|
|
(loop for num in numbers
|
|
for flag in mask
|
|
when (= flag 1)
|
|
sum num))
|
|
|
|
(defun find-sum (target numbers)
|
|
"Перебирает все комбинации (через битовые маски) для поиска целевой суммы."
|
|
(let* ((len (length numbers))
|
|
(total-combinations (1- (expt 2 len))))
|
|
(loop for index from 0 to total-combinations
|
|
for mask = (ten-to-bin index)
|
|
for current-sum = (calculate-sum numbers mask)
|
|
do (when (= current-sum target)
|
|
(format t "OK: ~A~%" mask)
|
|
(return-from find-sum mask)))
|
|
(progn
|
|
(format t "NO: not found ~%")
|
|
'())))
|
|
|
|
(defun main (&rest args)
|
|
(let ((len (length args)))
|
|
(if (or (< len 5) (> len 30))
|
|
(progn
|
|
(format t "ER: input parameters~%")
|
|
(uiop:quit 1))
|
|
(let ((target (parse-integer (first args)))
|
|
(numbers (mapcar #'parse-integer (rest args))))
|
|
(find-sum target numbers)))))
|