lisp lang solution № 2
This commit is contained in:
parent
5983863625
commit
8a3a35064e
2 changed files with 120 additions and 0 deletions
67
lisp/ros/solution2.ros
Executable file
67
lisp/ros/solution2.ros
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
#!/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 len mask)
|
||||
"Преобразует число в список бит (оптимизировано через сдвиги)"
|
||||
(declare (optimize (speed 3) (safety 0))
|
||||
(type fixnum x len)
|
||||
(type (simple-array fixnum (*)) mask))
|
||||
|
||||
(let ((i 0))
|
||||
(declare (type fixnum i))
|
||||
;; Пока число не 0 и мы в пределах len
|
||||
(loop while (and (> x 0) (< i len)) do
|
||||
(setf (aref mask i) (logand x 1)) ; (x & 1)
|
||||
(setf x (ash x -1)) ; (x >>= 1)
|
||||
(incf i))
|
||||
i))
|
||||
|
||||
(defun calculate-sum (len numbers mask)
|
||||
(declare (type fixnum len)
|
||||
(type (simple-array fixnum (*)) numbers mask))
|
||||
|
||||
(let ((sum 0))
|
||||
(declare (type fixnum sum))
|
||||
(dotimes (i len sum)
|
||||
(setf sum (the fixnum (+ sum (the fixnum (* (aref numbers i) (aref mask i)))))))))
|
||||
|
||||
(defun find-sum (target len numbers mask)
|
||||
"Перебирает все комбинации (через битовые маски) для поиска целевой суммы."
|
||||
(declare (optimize (speed 3) (safety 0))
|
||||
(type (simple-array fixnum(*)) numbers)
|
||||
(type (simple-array fixnum(*)) mask)
|
||||
(type fixnum target)
|
||||
(type (integer 0 62) len))
|
||||
|
||||
(let* ((total-combinations
|
||||
(1- (ash 1 (the (integer 0 61) (- len 1))))))
|
||||
(declare (type fixnum total-combinations))
|
||||
(format t "~D~%" total-combinations)
|
||||
(loop for i from 0 to total-combinations do
|
||||
(let* ((current-sum (calculate-sum (ten-to-bin i len mask) numbers mask)))
|
||||
(declare (type fixnum current-sum))
|
||||
(when (= current-sum target)
|
||||
(return mask))))))
|
||||
|
||||
(defun main (&rest args)
|
||||
(if (or (< (length args) 5) (> (length args) 30))
|
||||
(progn
|
||||
(format t "ER: input parameters~%")
|
||||
(uiop:quit 1))
|
||||
(progn
|
||||
(let* ((len (length args))
|
||||
(target (parse-integer (first args)))
|
||||
(mask (make-array len :element-type 'fixnum :initial-element 0))
|
||||
(numbers (coerce (mapcar #'parse-integer (rest args)) '(simple-array fixnum (*)))))
|
||||
(find-sum target len numbers mask)))))
|
||||
53
lisp/solution2.lisp
Normal file
53
lisp/solution2.lisp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
(defun ten-to-bin (x len mask)
|
||||
"Преобразует число в список бит (оптимизировано через сдвиги)"
|
||||
(declare (optimize (speed 3) (safety 0))
|
||||
(type fixnum x len)
|
||||
(type (simple-array fixnum (*)) mask))
|
||||
|
||||
(let ((i 0))
|
||||
(declare (type fixnum i))
|
||||
;; Пока число не 0 и мы в пределах len
|
||||
(loop while (and (> x 0) (< i len)) do
|
||||
(setf (aref mask i) (logand x 1)) ; (x & 1)
|
||||
(setf x (ash x -1)) ; (x >>= 1)
|
||||
(incf i))
|
||||
i))
|
||||
|
||||
(defun calculate-sum (len numbers mask)
|
||||
(declare (type fixnum len)
|
||||
(type (simple-array fixnum (*)) numbers mask))
|
||||
|
||||
(let ((sum 0))
|
||||
(declare (type fixnum sum))
|
||||
(dotimes (i len sum)
|
||||
(setf sum (the fixnum (+ sum (the fixnum (* (aref numbers i) (aref mask i)))))))))
|
||||
|
||||
(defun find-sum (target len numbers mask)
|
||||
"Перебирает все комбинации (через битовые маски) для поиска целевой суммы."
|
||||
(declare (optimize (speed 3) (safety 0))
|
||||
(type (simple-array fixnum(*)) numbers)
|
||||
(type (simple-array fixnum(*)) mask)
|
||||
(type fixnum target)
|
||||
(type (integer 0 62) len))
|
||||
|
||||
(let* ((total-combinations
|
||||
(1- (ash 1 (the (integer 0 61) (- len 1))))))
|
||||
(declare (type fixnum total-combinations))
|
||||
(format t "~D~%" total-combinations)
|
||||
(loop for i from 0 to total-combinations do
|
||||
(let* ((current-sum (calculate-sum (ten-to-bin i len mask) numbers mask)))
|
||||
(declare (type fixnum current-sum))
|
||||
(when (= current-sum target)
|
||||
(return mask))))))
|
||||
|
||||
(defun main (args)
|
||||
(if (or (< (length args) 5) (> (length args) 30))
|
||||
(progn
|
||||
(format t "ER: input parameters~%")
|
||||
(uiop:quit 1))
|
||||
(progn
|
||||
(let* ((len (length args))
|
||||
(target (parse-integer (first args)))
|
||||
(mask (make-array len :element-type 'fixnum :initial-element 0))
|
||||
(numbers (coerce (mapcar #'parse-integer (rest args)) '(simple-array fixnum (*)))))
|
||||
(find-sum target len numbers mask)))))
|
||||
Loading…
Add table
Add a link
Reference in a new issue