diff --git a/lisp/ros/solution1.ros b/lisp/ros/solution1.ros new file mode 100755 index 0000000..0158af5 --- /dev/null +++ b/lisp/ros/solution1.ros @@ -0,0 +1,53 @@ +#!/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))))) diff --git a/lisp/solution1.lisp b/lisp/solution1.lisp new file mode 100644 index 0000000..8f1d876 --- /dev/null +++ b/lisp/solution1.lisp @@ -0,0 +1,39 @@ +(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 (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))))) diff --git a/lisp/test.txt b/lisp/test.txt new file mode 100644 index 0000000..3d4e279 --- /dev/null +++ b/lisp/test.txt @@ -0,0 +1,11 @@ +(ten-to-bin 99) + +(main '("382040" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000")) + +(main '("477550" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000" "15800" "1525" "35300" "19410" "25000")) + +(time (dotimes (i 1000000) (calculate-sum #(1 2 3 4 5 6 7 8 9 10 11 12 13) #(1 1 1 0 1 1 0 0 1 1 1 0 0 0)) )) + +(time (dotimes (i 1000) (main-one '("69" "12" "1" "2" "11" "12" "1" "2" "11" "12" "1" "2" "11")))) + +