אנחנו ממשיכים באימון לקראת Advent Of Code של השנה ועוברים לתרגיל של היום השני. גם הפעם יש שני חלקים לתרגיל אז בשישי בבוקר אפרסם כאן את החלק השני ובמוצ״ש הפיתרונות וסיכום.
ספרת ביקורת
כשמעבירים מידע מצד לצד בתקשורת מקובל להוסיף ספרת ביקורת שתפקידה לוודא שהמידע לא התקלקל בדרך בטעות. דוגמא שאתם בטח מכירים היא תעודת הזהות בה הספרה הימנית ביותר היא ספרת ביקורת שעוזרת לוודא שלא טעיתם בהקלדת אחת הספרות האחרות. אפשר לקרוא עוד על המנגנון בויקיפדיה כאן:
בתרגיל של היום עלינו לחשב ספרת ביקורת לגיליון נתונים לפי הכללים הבאים: בכל שורה יש לקחת את ההפרש בין הערך הגדול ביותר לערך הקטן ביותר ולסכום את כל ההפרשים. התוצאה היא ספרת הביקורת של הגיליון.
לדוגמא בגיליון הנתונים הבא:
5 1 9 5
7 5 3
2 4 6 8
בשורה הראשונה הערך הגדול ביותר הוא 9 והקטן ביותר הוא 1. ההפרש ביניהם הוא 8.
בשורה השניה הערך הגדול ביותר הוא 7 והקטן ביותר 3. ההפרש ביניהם הוא 4.
בשורה השלישית הערך הגדול ביותר הוא 8 והקטן ביותר 2. ההפרש ביניהם הוא 6.
סכום ההפרשים הוא 18 (8+4+6) ולכן זו ספרת הביקורת של הגיליון.
כתבו קוד שמקבל גיליון (למשל קורא את הנתונים מקובץ) ומחשב את סיפרת הביקורת עליו. אחרי זה לכו לחידה אצל אריק וקחו ממנו את הקלט שלכם כדי לקבל את הכוכב. זה הקישור: https://adventofcode.com/2017/day/2
הי,
הפתרון הבא פותר את התרגיל אבל כשניסיתי את הקלט הארוך של אריק התשובה לא היתה נכונה.
לא הבנתי מדוע
path_r = r"C:\Python\Advent_of_code\exercise_2.txt"
temp = 0
with open(path_r,"r") as f_r:
a = [line.split() for line in f_r]
for i in a:
for j in i:
temp += int(max(j)) - int(min(j))
print temp
/** Receives input as String and split it by new-line token.
For each line, calculate difference of max and min. */
public static int checksum(String input) {
String[] lines = input.split("\n");
int sum = 0;
for(String line : lines)
sum += greatestDiff(line);
return sum;
}
/** Receives a line of values, split it by whitespaces and tabs.
Init max and min as first value, then iterate over values to find min and max. */
public static int greatestDiff(String line) {
String[] values = line.split("[ \t]+"); //one or more whitespaces/tabs
int max = Integer.parseInt(values[0]), min = max;
for(int i=1, n=values.length; i < n; i++) {
int curr = Integer.parseInt(values[i]);
if(curr > max) max = curr;
else if(curr < min) min = curr;
}
return max - min;
}
.
חלק ב’ (שימוש במתודה checksum):
/** Receives a line of values, split by whitespaces and tabs.
Init an array of type int and parse values from String[].
For each value, check if division with other values givse a whioe value. */
public static int evenDivision(String line) {
String[] values = line.split("[ \t]+");
int len = values.length;
int[] nums = new int[len];
for(int i=0; i < len; i++)
nums[i] = Integer.parseInt(values[i]);
for(int i=0; i < len; i++)
for(int j=0; j < len; j++) {
if (i==j) continue;
if (nums[i] % nums[j] == 0)
return nums[i] / nums[j];
}
throw new RuntimeException("Could not find two values that divide to a whole number");
}
ספציפית כאן כמו שאמרת כנראה לא יעזור כי הפונקציות map ו reduce ב JavaScript לקחו את הגישה מונחית העצמים ומופעלות עם נקודה (כמו ב Ruby). זה יותר רלוונטי לפונקציות ספריה שמקבלות את ה״אוביקט״ שעובדות עליו בתור הפרמטר הראשון (בדומה לשפות פונקציונאליות). למשל פונקציות כמו JSON.parse
טוב לפי הפלט שלך נראה שיש לי פה פספוס על ההתחלה
סכום הפרשים של השורה הראשונה אצלי הוא 99
לפי החישוב שלי זה גם נכון כי ביקשו את סכום ההפרשים של כל מספר בשורה (כלומר הספרה הגדולה פחות הספרה הקטנה בכל מספר) וזה אכן כך…
איך זה יוצא 2156 ?
public static int checkDifference() throws FileNotFoundException {
Scanner scan = new Scanner(new File("path"));
int sum = 0;
while (scan.hasNextLine()) {
String line = scan.nextLine();
String[] arrayLineStr = line.split("\t");
int[] arrayInt = Arrays.asList(arrayLineStr).stream().mapToInt(Integer::parseInt).toArray();
int high = 0;
int low = arrayInt[0];
for (int i : arrayInt) {
if (i > high) {high = i;}
if (i < low) {low = i;}
}
sum += (high - low);
}
return sum;
}
וזה לחלק השני
public static int checkDifference2() throws FileNotFoundException {
Scanner scan = new Scanner(new File("C:path"));
int sum = 0;
while (scan.hasNextLine()) {
String line = scan.nextLine();
String[] arrayLineStr = line.split("\t");
int[] arrayInt = Arrays.asList(arrayLineStr).stream().mapToInt(Integer::parseInt).toArray();
boolean find = false;
for (int i : arrayInt) {
for (int j : arrayInt) {
if (i != j) {
if (i % j == 0) {
sum += (i / j);
find = true;
break;
}
}//if i != j
}
if (find == true) break;
}
}
return sum;
}