תרגול חזרה לבוחן
DESCRIPTION
תרגול חזרה לבוחן. נמרוד מילוא. Decimal system: Ten digits: 0,1,2,3,…,9. 3185. = 3*1000 + 1*100 + 8*10 + 5*1. = 3* 10^3 + 1* 10^2 + 8* 10^1 + 5* 10^0. Binary system: Two digits: 0,1. 10110. 1*(2^4) + 0*(2^3) + 1*(2^2) + 1*(2^1) + 0*(2^0). Byte and Bit. Binary to Decimal. - PowerPoint PPT PresentationTRANSCRIPT
תרגול חזרה לבוחן
נמרוד מילוא
3185
= 3*1000 + 1*100 + 8*10 + 5*1
= 3*10^3 + 1*10^2 + 8*10^1 + 5*10^0
Decimal system:
Ten digits: 0,1,2,3,…,9
10110
1*(2^4) + 0*(2^3) + 1*(2^2) + 1*(2^1) + 0*(2^0)
Binary system:
Two digits: 0,1
Byte and Bit
00001011
*
2^7
*
2^6
*
2^5
*
2^4
*
2^3
*
2^2
*
2^1
*
2^0
Binary to Decimal
00001011
0)*2^7(0)*2^6(0)*2^5(0)*2^4(1)*2^3(0)*2^2(1)*2^1(1)*2^0(
2^3 + 2^1 + 2^0 = 11
Decimal to Binary
251 [25%2=1]
12 [25/2=12]0 [12%2=0]
6 [12/2=6]0 [6%2=0]
3[ 6/2=2]1 [3%2=1]
1 [3/2=1]1 [1%2=1]
0 [1/2=0]
Right
Left
25 (decimal) = 11001 (binary)
7
פרימיטיבי. vs אינו פרימיטיבי משתנה שאינו
פרימיטיבימשתנה פרימיטיבי
מה נמצא הערך עצמו הכתובתבטבלת המשתנים
השמה הערך מועתק הכתובת מועתקת
השוואה בין כתובות
(==) השוואה בין ערכיםהשוואה
8
מבנה של פונקציהpublic static <return type> <func name> (<arg1_type> <arg1>, <arg2_type> <arg2>, …) {
>function body<
}
חתימה של פונקציה מורכבת משם הפונקציה ומרשימת •סוגי , טיפוסי הארגומנטים שהפונקציה מקבלת (מספר
טיפוסים וסדר)לכל שתי פונקציות בתכנית חתימה שונה• publicכגון )הערך המוחזר וכן מאפיינים נוספים של פונקציה •
) אינם נכללים בחתימה של הפונקציהstaticו- public static int foo(int num)}…{ √public static int foo(int num1, double num2)}…{ √public static int foo(double num)}…{ √public static double foo(int num)}…{ X
9
public class Sum{public static void main)String[] args({
int lastInd = 10;int sum = sumNums)lastInd(;
System.out.println)“The sum of numbers from 1 to “+ lastInd+ “ = “ + sum(;
System.out.println)“The sum of numbers from 1 to “+ 8 + “ = “ + sumNums)8((;
}
// returns the sum of numbers from 1 to endpublic static int sumNums)int end( {
int sum = 0;for)int i = 1; i <= end; i = i+1(
sum = sum + i;return sum;
}}
10
בזמן קריאה לפונקציה:השליטה של התכנית שומרת את המיקום הנוכחי •
שלה ועוברת לפונקציה.נפתחת סביבה (טבלת משתנים) חדשה שבה •
מוגדרים הפרמטרים של הפונקציה והמשתנים .שמוגדרים בתוך הפונקציה
(או סיום הפונקציה במקרה של returnההוראה •void סוגרת את הסביבה ומחזירה את השליטה (
למקום בו היינו לפני הקריאה לפונקציה
•Flow of previous func
main
sumNums(10)
11
public class Sum{public static void main)String[] args({
int lastInd = 10;int sum = sumNums)lastInd (;
System.out.println)“The sum of numbers from 1 to “+ lastInd + “ = “ + sum(;System.out.println)“The sum of numbers from 1 to “+ 8 + “ = “ + sumNums)8((;
}
// returns the sum of numbers from 1 to endpublic static int sumNums)int end( {
int sum = 0;for)int i = 1; i <= end; i = i+1(
sum = sum + i;return sum;
}}
endint10
sumint0lastIndint10
sumint55 sumint iint1
155
העברת משתנים לפונקציה
12
מועברים בעת קריאה לפונקציה בעלת Javaב-פרמטרים, הערכים הרשומים בטבלת המשתנים, בין אם
מדובר בערך ממש או בכתובת:
מה שיעבור - אם הפרמטר הוא מטיפוס פרימיטיבי,ולכן הפונקציה לא , לפונקציה הוא הערך של המשתנה.תוכל לשנות את המשתנה המקורי
- אם הפרמטר הוא מטיפוס שאינו פרימיטיבי, כלומר מכיל מצביע לאובייקט (כגון מערך), אז הפונקציה
מקבלת את הכתובת, ויכולה לשנות את האובייקט בזיכרון.
13
דוגמא להעברת פרמטרים מטיפוס פרימיטיבי:
public static void main(String[] args){
int x=8;
System.out.println(x);
add5(x);
System.out.println (x);
}
public static void add5(int x){
x = x+5;
System.out.println (x);
}
14
מה היינו עושים?xאם היינו רוצים לשנות את הערך של xכך שתחזיר ערך ואותו להכניס ל add5 היינו צריכים לשנות את
:
public static void main(String[] args){
int x=8;
System.out.println(x);
x=add5(x);
System.out.println(x);
}
public static int add5(int x) {
x = x+5;
System.out.println(x);
return x;
}
15
public static void main(String[] arg){int [] x={1,2,3};printArray(x);add5(x);printArray(x);
}
public static void add5(int[] y) {for (int i=0 ; i<y.length ;i=i+1)
y[i] = y[i]+5;printArray (y);
}
דוגמא להעברת פרמטרים מטיפוס לא פרימיטיבי:
/*/* outputoutput1 2 31 2 36 7 86 7 86 7 86 7 8*/*/
123
מחרוזותהקדמה
) היא מחלקה המייצגת טקסט (רצף של תווים). Stringמחרוזת (
ונגמר באורך 0מיספור אינדקס התווים במחרוזת מתחיל מ
.1המחרוזת פחות
String "abcd"
Index 0123
מבוא למדעי המחשב, בן גוריון תשע"א16
מחרוזותפעולות על מחרוזות:
הגדרה ואתחול•
String s1;
String s2 = "abcd";
String s3 = null;
String s4 = "";
String s5 = new String)(;
מבוא למדעי המחשב, בן גוריון תשע"א17
מחרוזות
אורך•
s2.length)(4
s3.length)(
NullPointerException
s4.length)(0
18
String s2 = "abcd";
String s3 = null;
String s4 = "";
מבוא למדעי המחשב, בן גוריון תשע"א
מחרוזות
תו במיקום (אינדקס) מסוים•
s2.charAt)0(
s2.charAt)1(
s2.charAt)5(
19
String s2 = "abcd";
'a'
'b'
StringIndexOutOfBoundsException
:String index out of range
מבוא למדעי המחשב, בן גוריון תשע"א
מחרוזות
).j (לא כולל את j ועד אינדקס i החל מאינדקס תת-מחרוזת•
s2.substring)1,3( "bc"
s2.substring)1( "bcd"
).false או true בין תוכן שתי מחרוזות. התוצאה בוליאנית (השוואה•
s2.equals)s4(
+ שרשור•
s2+"efg" יוצר מחרוזת חדשה "abcdefg" המחרוזת .s2.לא משתנה
20
String s2 = "abcd";
מבוא למדעי המחשב, בן גוריון תשע"א
מחרוזות
– מחרוזת עם סדר תווים הפוך 1דוגמה
המקבלת מחרוזת reverseלפנינו פונקציה
ומחזירה מחרוזת אחרת שבה התווים של
reverse בסדר (מיקום) הפוך. הפונקציה
על המחרוזת reverseהראשית מפעילה את
"Hello") ומדפיסה את התוצאה olleH.(
מבוא למדעי המחשב, בן גוריון תשע"א21
public class StringReverser {
public static String reverse) String data ( {
String rev = new String)(;
for ) int j=data.length)(-1; j>=0; j=j-1 (
rev = rev + data.charAt)j(;
return rev;
}
public static void main ) String[] args ( {
System.out.println) reverse) "Hello" ( (;
}
}
מבוא למדעי המחשב, בן גוריון תשע"א22
מחרוזות – חיפוש של תת-מחרוזת במחרוזת2דוגמה
sub ו- str המקבלת שתי מחרוזת isSubstringלפנינו פונקציה
כתת מחרוזת. הפונקציה str מופיעה בתוך subובודקת האם
מחזירה תשובה בוליאנית.
באינדקס " abcd" מופיעה כתת-מחרוזת במחרוזת "bc"למשל, המחרוזת
1.
String "abcd"
Index 0123
בעלות אורך זהה."abcd" לתתי מחרוזות של "bc"נשווה את
מבוא למדעי המחשב, בן גוריון תשע"א23
public static boolean isSubstring)String str,String sub({
boolean found = false;
int lastInd = str.length)(- sub.length)(;
for ) int i=0; i<=lastInd && !found; i=i+1( {
String strSub = str.substring)i, i+sub.length)((;
if )strSub.equals)sub((
found = true;
}
return found;
}
מבוא למדעי המחשב, בן גוריון תשע"א24
ASCIIטבלת
מחרוזות– צופן קיסר 3דוגמה
טקסט ) הוא אלגוריתם הצפנה, המקבל Cipherצופן (. טקסט מוצפן - ומחזיר מפתח וקריא
צופן קיסר מבוסס על רעיון החלפת האותיות של •הטקסט הקריא לשם יצירתו של הטקסט המוצפן:
האלפבית המשמש להצפנה מוסט מעגלית במספר קבוע של 'מקומות' מן האלפבית הרגיל.
)= מספר מקומות ההסטה keyהמפתח (•
לפי עדויות היסטוריות יוליוס קיסר עשה בשיטה זו •שימוש נרחב.
מבוא למדעי המחשב, בן גוריון תשע"א26
מחרוזות
BABY מקומות המילה3למשל, בהזזת של תתורגם...
.EDEBלמילה
מבוא למדעי המחשב, בן גוריון תשע"א27
public static String encrypt)String str, int key( {
String ans = "";
final int NUM_OF_LETTERS_IN_ALPHABET = 26;
for)int i = 0; i < str.length)(; i=i+1( {
int c = str.charAt)i(;
if )'A'<=c & c<='Z'( {
c = c - 'A';
c = ))c + key( % NUM_OF_LETTERS_IN_ALPHABET(+'A';
}
else if )'a'<=c & c<='z'({
c = c - 'a';
c = ))c + key( % NUM_OF_LETTERS_IN_ALPHABET(+'a';
}
ans = ans + )char(c;
}
return ans;
}
מבוא למדעי המחשב, בן גוריון תשע"א28
מחרוזות:כמה הערות
; )int c = str.charAt)iבפקודה 1.
.int ל charמתרחשת המרת טיפוס אוטומאטית מ
. 'c - 'A ו- A'<=c' כנ"ל בביטויים כמו
; ans = ans + )char(cבפקודה 2.
. פעולה זו נחוצה מכיוון char ל intיש המרת טיפוס מפורשת מ
.int (65) ולא char ('A')שנרצה לשרשר למחרוזת התוצאה ערך
, ASCIIהערכים המספריים של כל תו מסוכמים בטבלה (טבלת 3.
). אין כלל צורך לזכור את הטבלה בע"פ.UNICODEתקן
מבוא למדעי המחשב, בן גוריון תשע"א29
מחרוזותpublic static void main)String[] args( {
String str = "BEN GURION UNIVERSITY";
int key = 3;
String encrypted = encrypt)str, key(;
System.out.println)encrypted(;// "EHQ JXULRQ XQLYHUVLWB"
String decrypted = decrypt)encrypted, key(;
System.out.println)decrypted(;// "BEN GURION UNIVERSITY"
}
: מהי פעולת פענוחשאלה (decrypt) של צופן קיסר?
: בדומה להצפנה, מלבד חיסור של מפתח ההזזה במקום חיבורותשובה .
מבוא למדעי המחשב, בן גוריון תשע"א30
מחרוזות
פריצת צופן קיסרבהינתן טקסט מוצפן כיצד ניתן לגלות את הטקסט •
הקריא מבלי לדעת את המפתח?ניתן לנחש את המפתח בו הוצפן הטקסט •
באמצעות סטטיסטיקה על השכיחויות של אותיות האלף בית האנגלי בטקסט כלשהו. האות השכיחה
.12%, שכיחותה Eביותר בטקסט באנגלית היא הבא תכתוב תוכנית המוצאת את האות quizב –•
השכיחה ביותר בטקסט נתון. סביר להניח שאות זו וככה ניתן לחשב בכמה Eהיא הקידוד של האות
הזזנו את האותיות.
מבוא למדעי המחשב, בן גוריון תשע"א31
מיונים
) - הגדרת הבעיה: בהינתן array sortמיון מערך ( מספרים שלמים חשב מערך ממוין n של Aמערך
של אותם מספרים.
למשל:Input: 7 , 18, 28 , 4, 10Output: 4, 7, 10 , 18 , 28
ישנם שיטות מיון רבות, כמו: מיון בחירה, מיון הכנסה ומיון בועות.
מבוא למדעי המחשב, בן גוריון תשע"א32
מיונים
)Bubble Sort(מיון בועות
תיאור השיטה:תוך כדי המיון, החלק הימני של המערך כבר ממוין
("מעל פני הים") והחלק השמאלי של המערך אינו ממוין ("מתחת לפני הים").
בכל סבב, "בועה" מבעבעת עד שהיא מגיעה לפני הים. הבועה "סוחבת" איתה ערכים גדולים:
בביעבוע הבועה, בכל שני תאים סמוכים בהן עוברת הבועה, מוחלפים הערכים אם הם לא
בסדר המיון.
מבוא למדעי המחשב, בן גוריון תשע"א33
מיונים
34
וכן הלאה עד אשר המערך כולו מעל פני הים.
http://www.youtube.com/watch?v=t_xkgcakREw&feature=related
מבוא למדעי המחשב, בן גוריון תשע"א
public static void bubbleSort)int[] array({
int tmp;
/* @pre: bbl=0 */
for )int bbl=0; bbl<array.length-1; bbl=bbl+1( {
/* @inv: array[array.length- bbl.. array.length-1] is sorted
* and all numbers array[array.length-bbl.. array.length-1]
* are bigger than the numbers array[0 .. array.length-bbl-1] */
for )int index=0; index < array.length-1; index=index+1( {
if )array[index] > array[index+1]( {
tmp = array[index];
array[index] = array[index+1];
array[index+1] = tmp;
}
}
}
/* @post: array is sorted */
} מבוא למדעי המחשב, בן גוריון תשע"א35
מיונים
(array[index] > array[index+1]): כמה השוואות מתבצעות? שאלה
השוואות. הלולאה n: הלולאה הפנימית מבצעת תשובה פעמים. nהחיצונית מתבצעת
השוואות. n2 סה"כ
: האם כל ההשואות נחוצות? שאלה: לא. תשובה
אם המערך כבר ממוין אין צורך להמשיך בלולאה. (לא •צריך לבעבע עוד בועה)
השוואות הנעשות בחלק הממויין מיותרות. (פני הים •יורדים, ויש להשוות איברים רק מתחת לפני הים)
מבוא למדעי המחשב, בן גוריון תשע"א36
public static void bubbleSort)int[] array({
boolean isSorted = false;
int tmp;
for )int bbl=0; !isSorted && bbl<array.length-1; bbl=bbl+1({
isSorted = true;
for )int index=0; index<array.length-1-bbl; index=index+1({
if )array[index] > array[index+1]( {
tmp = array[index];
array[index] = array[index+1];
array[index+1] = tmp;
isSorted = false;
}
}
}
}
מבוא למדעי המחשב, בן גוריון תשע"א37
)Quick Sortמיון מהיר () שנבחר pivotחלוקת המערך לשני חלקים לפי ציר (
מחדש בכל שלב של הרקורסיה ומיון רקורסיבי של כל צד
הציר שנבחר הינו הערכה (ניחוש) של החציון של המספרים במערך
תזכורת: חציון הוא מדד למיקום המרכז של קבוצת נתונים מספריים. לדוגמא: החציון של קבוצת
8 הוא 16, 8, 19, 7, 22, 2, 1המספרים
נבחר בקוד שלנו את האיבר הראשון כציר.
38
- דוגמא )Quicksortמיון מהיר (
6151931221174
431 152117912
13 129 1721
9
134 6 912 15 1721
213
39
מיון מהיר – הקוד
import java.util.Scanner;
public class QuickSort {public static void main)String[] args({
Scanner sc = new Scanner)System.in(;System.out.println)"Enter number of elements to
sort:"(;int n = sc.nextInt)(;int[] arr = new int[n];// Initializes arr with random numbers // in [0..10*N(initRandomArray)arr(; System.out.println)"The input array:"(;printArray)arr(;quicksort)arr(;System.out.println)"The sorted array:"(;printArray)arr(;
} //…. continued 40
מיון מהיר – הקוד (המשך)
public static void swap)int[] arr, int i, int j({ // swap arr[i] and arr[j] int temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}
public static void initRandomArray)int[] arr({// shuffle the array arrint n = arr.length;for )int i = 0; i < n; i++( {
arr[i] = )int( )Math.random)( * 10 * n(; }
}public static void printArray )int[] arr( {
for )int i=0; i<arr.length; i=i+1(System.out.print )arr[i]+" "(;
System.out.println)(;} 41
מיון מהיר – הקוד (המשך)
public static void quicksort)int[] arr({quicksort)arr, 0, arr.length-1(;
}
public static void quicksort)int[] arr, int start, int end({if )start<end({
int i = partition)arr, start, end(;quicksort)arr, start, i-1(;quicksort)arr, i+1, end(;
}}
42
מיון מהיר – הקוד (המשך)
public static int partition)int[] arr, int start, int end({int pivot = arr[start];int i = start;int j = end;while)i<j({
while)i<end && arr[i] <= pivot(i=i+1;
while)arr[j] > pivot( j=j-1;
if )i<j( swap)arr,i,j(;
}
swap)arr,start,j(;return j;
}
43
הדפסת הפרמוטציות של מחרוזת
פרמוטציה של מחרוזת מוגדרת כמחרוזת המכילה את אותן •אותיות, ייתכן שבשינוי סדר. נניח בדוגמה זו שכל האותיות
שונות זו מזו.
: הםbcdהמחרוזת למשל הפרמוטציות עבור •–“bcd "–“bdc "–“cbd“–“cdb”–“dbc“–“dcb”
44
הרעיון של הרקורסיה
45
abcd,””
bcd, “a”
abcd,””
bcd, “a”
cd, “a” + “b”cd, “a” + “b”
abcdd, “a” + “b” + “c”
““, “a” + “b” + “c” +”d”
output:
i=0
i=0
i=0
i=0i=1i האינדקס =
שלפיו מחלקים את
המחרוזת
הרעיון של הרקורסיה
46
abcd,””
bcd, “a”
abcd,””
bcd, “a”
cd, “a” + “b”cd, “a” + “b”
abcdd, “a” + “b” + “c”
““, “a” + “b” + “c” +”d”
output:
i=0
i=0
i=0
i=1
i=1
הרעיון של הרקורסיה
47
abcd,””
bcd, “a”
cd, “a” + “b”
d, “a” + “b” + “c”
abcd,””
bcd, “a”
cd, “a” + “b”
““, “a” + “b” + “c” +”d”
abcd
c, “a” + “b” + “d”
“”, “a” + “b” + “d” + “c”
abdcoutput:
output:
i=0
i=0
i=1i=2
הרעיון של הרקורסיה
48
abcd,””
bcd, “a”
cd, “a” + “b”
d, “a” + “b” + “c”
abcd,””
bcd, “a”
cd, “a” + “b”
““, “a” + “b” + “c” +”d”
abcd
c, “a” + “b” + “d”
“”, “a” + “b” + “d” + “c”
abdc
bd, “a” + “c”bd, “a” + “c”
d, “a” + “c” + “b”
“”, “a” + “c” + “b” + “d”
acbd
output:
output:
output:
i=0
i=1
i=1
i=1
הרעיון של הרקורסיה
abcd,””
bcd, “a”
cd, “a” + “b”
d, “a” + “b” + “c”
abcd,””
bcd, “a”
cd, “a” + “b”
““, “a” + “b” + “c” +”d”
abcd
c, “a” + “b” + “d”
“”, “a” + “b” + “d” + “c”
abdc
bd, “a” + “c”bd, “a” + “c”
d, “a” + “c” + “b”
“”, “a” + “c” + “b” + “d”
acbd
output:
output:
output:bc, “a” + “d”
. . .
. . .
i=3
49
: הדפסת 3קוד של דוגמה הפרמוטציות של מחרוזת
public static void perms(String s){ // We call the method perm(s,"") which prints // the empty string followed by each permutation // of s the empty string.
perms(s,"");}
50
/** Function prints all the permutation of a string. * Note: assume the string is a set (no duplicate * chars) */
// Prints string acc followed by all permutations of // string s1 public static void perms)String s1, String acc({ if )s1.length)(==0( System.out.println)acc(; else for )int i=0; i<s1.length)(; i=i+1( perms)delete)s1, i(, acc +s1.charAt)i((;}
: הדפסת 3קוד של דוגמה הפרמוטציות של מחרוזת
51
deleteפונק' עזר:
// This function returns the string s with the i-th // character removedpublic static String delete)String s, int i({
// Assumes that i is a position in the stringreturn s.substring)0,i( +
s.substring)i+1,s.length)((;}
52
- 4דוגמה הרכבת סכום נתון ממשקולות
בהינתן מערך משקולות אי-שליליים ומשקל נוסף (משקל סכום), נרצה לבדוק האם ניתן להרכיב מהמשקולות
משקל השווה למשקל הסכום הנתון.
דוגמא לקלט:•weights=}1,7,9,3{ Sum = 12
כי ניתן לחבר את trueבמקרה זה הפונקציה תחזיר .12 ולקבל את הסכום 3 ו 9המשקולות
דוגמא לקלט: •weights=}1,7,9,3{ Sum = 15
כי לא ניתן לחבר falseבמקרה זה הפונקציה תחזיר .15משקולות לקבלת הסכום
53
תיאור פתרון נתבונן באיבר הראשון במערך. ייתכן שהוא ייבחר
לקבוצת המשקולות שתרכיב את הפתרון ויתכן שלא. אם הוא לא ייבחר )להיות כלול בסכום המהווה את
משקל המטרה( – אזי נותר לפתור בעיה קטנה יותר והיא האם ניתן להרכיב את הסכום מבין המשקולות
שנותרו במערך. אם הוא ייבחר – אזי נותר לפתור בעיה קטנה יותר
והיא האם ניתן להרכיב את הסכום שנותר מבין .המשקולות שנותרו במערך
.וכנ"ל לגבי יתר האיברים בצורה רקורסיבית
54
תיאור פתרון - המשך
פתרון זה קל להציג כפונקציה רקורסיבית ,•boolean calcWeights(int[] weights, int i, int sum )
הפונקציה מחזירה ערך אמת האם ניתן להרכיב את •הסכום מבין קבוצת המשקולות שבתת המערך.
הפרמטרים: •weightsמערך המשקולות – sumהסכום שיש להרכיב מהמשקולות – i .פרמטר נוסף הנחוץ עבור הרקורסיה – i הוא אינדקס
ויסמן את האיבר הנוכחי במערך עליו weightsבמערך מתבצעת הקריאה הרקורסיבית.
55
50:
50: [20,30]
40: [20,30]
40: [30]
40: []
10: []
20: [30]
20: []
-10[]
i=1
i=3
[10,20,30]
i=0
i=2
56
50:
50: [20,30]
i=1
30: [30]
0: []
50: [30]
i=350: []
i=2
20: []
30: []
[10,20,30]
40: [20,30]
i=0
האם צריך לחשבענף ?ימני
57
calcWeights: 4קוד דוגמה
הארגומנטi נחוץ עבור הרקורסיה – אך אינו באמת חלק מהקלט של הבעיה. בקריאה הראשונה ל
calcWeights לכן נוסיף פונקצית 0 ערכו הוא .מעטפת עם חתימה פשוטה יותר.
//An envelope function, without i argument //A simpler signature
public static boolean calcWeights(int[] weights, int sum) { return calcWeights(weights , 0, sum) ;
}
58
פתרון (המשך)public static boolean calcWeights)int[] weights,
int i, int sum { (
boolean res = false ;
if )sum == 0(
res = true ;
else if )i >= weights.length(
res = false ;
else
res = calcWeights)weights,i+1,sum-weights[i]( || calcWeights)weights, i + 1, sum(;
return res;
}
59