Հանդիպեցի մի խնդրի, որտեղ պետք էր Common Lisp վեկտորից (միչափանի զանգված), որի տարրերը (0..255) միջակայքի ամբողջ թվեր են, ստանալ նրա տարրերի ցուցակը և այդ նույն տարրերի տասնվեցական ներկայացումներից բաղկացած տողը։ Օրինակ, վեկտորը կարող է լինել այսպիսին.
(defparameter vec
#(12 34 210 127 32 7 25 87 193 41 42 200 63 0 137 161))
(print vec)
#(12 34 210 127 32 7 25 87 193 41 42 200 63 0 137 161)
Դե, առաջին միտքն այն էր, որ
loop
ցիկլով կարելի է անցնել վեկտորի տարրերով և դրանք հավաքել ցուցակի մեջ.
(defparameter veclis
(loop for e across vec collect e))
(print veclis)
(12 34 210 127 32 7 25 87 193 41 42 200 63 0 137 161)
Իսկ տասնվեցական նիշերից կազմված տողը ստանալու համար կարելի է
format
ֆունկցիայով ստանալ թվի տասնվեցական ներկայացումը՝ օգտագործելով
"~2,'0x"
ֆորմատավորման տողը։ Այդ տասնվեցական տեսքերը հավաքել ցուցակի մեջ, ապա այդ ցուցակի նկատմամբ կիրառել
concatenate
ֆունկցիան, իհարկե,
apply
ֆունկցիայի միջոցով։
(defparameter vecstr
(apply #'concatenate 'string
(loop for e across vec
collect (format nil "~2,'0x" e))))
(print vecstr)
"0C22D27F20071957C1292AC83F0089A1"
* * *
Բայց, սրանք շատ տգեղ պրոցեդուրային լուծումներ են։ Common Lisp լեզվի
reduce
ֆունկցիան արգումենտում ստանում է բինար ֆունկցիա և մի որևէ հաջորդականություն, իսկ վերադաձնում է մի արդյունք, որը ստացվում է հաջորդականության բոլոր տարրերի միջև կիրառելով տրված բինար գործողությունը։ Օրինակ, եթե վեկտորը պարունակում է 1-ից 9 թվերը, ապա դրանց գումարը հաշվելու համար կարելի է գրել.
(reduce #'+
#(1 2 3 4 5 6 7 8 9)
:initial-value 0)
45
Իսկ նույն այդ վեկտորի թվերի քառակուսիների գումարը հաշվելու համար՝
(reduce #'(lambda (a b) (+ a (* b b)))
#(1 2 3 4 5 6 7 8 9)
:initial-value 0)
285
Հիմա, վեկտորից ցուցակ ստանալու համար օգտագործենք
(lambda (x y) (cons y x))
ֆունկցիան և
'()
սկզբնական արժեքը։
reduce
ֆունկցիայի արժեքը ստացվում է շրջված տեսքով, դրա համար էլ լրացուցիչ կիրառվել է
reverse
ֆունկցիան։
(defparameter veclis
(reverse (reduce #'(lambda (x y) (cons y x)) vec :initial-value '())))
(print veclis)
(12 34 210 127 32 7 25 87 193 41 42 200 63 0 137 161)
Տասնվեցական ներկայացումների տողը ստանալու համար կարելի է օգտագործել
(lambda (x y) (format nil "~a~2,'0x" x y))
ֆունկցիան։
(defparameter vecstr
(reduce #'(lambda (x y)
(format nil "~a~2,'0x" x y))
vec :initial-value ""))
(print vecstr)
"0C22D27F20071957C1292AC83F0089A1"
No comments:
Post a Comment