Penyelesaian Hari ini adalah lebih kompleks sedikit daripada hari sebelumnya yang menjamin lebih sedikit kod, tetapi bagaimanapun ia agak lurus ke hadapan.
Konsep asas penyelesaian:
Untuk menjadi sah, syarat berikut untuk Bahagian 1 mesti dipenuhi:
Kita perlu memutuskan sama ada bilangannya semakin meningkat, atau berkurangan dari satu ke seterusnya.
jurang antara nombor tidak boleh lebih daripada 3
var reports = File.ReadAllLines("./input1.txt") .Select(x => x.Split(" ")) .ToList(); Part1(reports); void Part1(List<string[]> input) { var validReports = input .Select(report => report.Select(int.Parse).ToList()) .Count(IsValidReport); Console.WriteLine(validReports); } bool IsValidReport(List<int> levels) { // We don't care about the numbers, just wether going up or down, not both var isIncreasing = IsIncreasing(levels); var isDecreasing = IsDecreasing(levels); if (!isIncreasing && !isDecreasing) return false; // Check that all adjacent levels differ by at least 1 and at most 3 for (var i = 0; i < levels.Count - 1; i++) { var diff = Math.Abs(levels[i + 1] - levels[i]); if (diff is < 1 or > 3) { return false; } } return true; } bool IsIncreasing(List<int> numbers) { for (var i = 1; i < numbers.Count; i++) { if (numbers[i] < numbers[i - 1]) return false; } return true; } bool IsDecreasing(List<int> numbers) { for (var i = 1; i < numbers.Count; i++) { if (numbers[i] > numbers[i - 1]) return false; } return true; }
Penjelasan mudah, ialah kami menggunakan LINQ menghuraikan nombor rentetan kepada integer sebelum menghantar laporan kepada kaedah IsValidReport() pembantu kami.
Kaedah ini menyemak sama ada semua nombor sama ada meningkat atau berkurangan. Ini dilakukan dengan membandingkan id dengan senarai tersusun, yang akan membuktikan semua nombor menuju ke satu arah.
Sebaik sahaja kami tahu mereka semua berada dalam satu arah (bukan band) kami boleh menyemak sama ada setiap nombor berada dalam lingkungan 3 nombor antara satu sama lain. Menggunakan kaedah Math.Abs(), yang mengembalikan nombor mutlak, membantu kami mengambil kira angka tolak.
Nota: nombor mutlak, ialah nombor antara nombor dan sifar, iaitu -5 dan 5 akan mengembalikan 5;
Untuk Bahagian 2, kami mempunyai arahan yang sama ada lebih kompleks, tetapi kedengarannya lebih sukar daripada yang sebenarnya.
Bahagian kedua memperkenalkan kaveat kesilapan manusia, dengan konsep asas yang perlu anda ketahui jika anda boleh mengalih keluar mana-mana 1 item daripada laporan dan ia masih akan dianggap sebagai laporan yang sah.
void Part2(List<string[]> input) { var validReports = 0; foreach (var ints in input.Select(report => report.Select(int.Parse).ToList())) { // If valid as-is, count it if (IsValidReport(ints)) { validReports++; continue; } // Check if removing any single level makes it valid if (ints.Select((t, i) => ints.Where((_, index) => index != i).ToList()) .Any(IsValidReport)) { validReports++; } } Console.WriteLine(validReports); }
Di sini kami memaksimumkan kuasa LINQ, menghuraikan laporan rentetan, serta menggunakannya untuk mengubah suai tatasusunan ints. Kami mengubah suai dengan menggelung melalui tatasusunan dan mengalih keluar item semasa pada indeks, sekali gus mengubah suai tatasusunan int.
Setelah diubah suai, kami menjalankan laporan yang diubah suai melalui pengesah. Ini boleh dilakukan sekali gus menggunakan kaedah LINQ Select(), digabungkan dengan Any() yang akan litar pintas sebaik sahaja syarat dipenuhi (iaitu sebaik sahaja laporan yang diubah suai sah).
Ini kerana ia menyatakan jika mana-mana satu item boleh dialih keluar maka laporan tersebut boleh dianggap sah. Ia tidak menyatakan item tertentu, jadi sebaik sahaja kami menemui item sepadan yang apabila dialih keluar bermakna laporan itu sah, kami boleh berhenti melihat semua yang lain.
Kami kemudian menambah kaunter Laporan yang sah, untuk menjejaki laporan kami yang sah.
def main(): # Read the input file and split each line into a list of strings with open("./input1.txt") as file: reports = [line.split() for line in file] part1(reports) part2(reports) def part1(reports): # Count valid reports using a list comprehension and the IsValidReport function valid_reports = 0 for report in reports: levels = list(map(int, report)) if is_valid_report(levels): valid_reports += 1 print(valid_reports) def part2(reports): valid_reports = 0 for report in reports: ints = list(map(int, report)) # If valid as-is, count it if is_valid_report(ints): valid_reports += 1 continue # Check if removing any single level makes it valid valid_with_dampener = False # Iterate over each element in ints for i in range(len(ints)): # Create a new list without the element at index i modified_report = [x for j, x in enumerate(ints) if j != i] # Check if the modified report is valid if is_valid_report(modified_report): valid_with_dampener = True break if valid_with_dampener: valid_reports += 1 print(valid_reports) def is_valid_report(levels): # Check if the sequence is either all increasing or all decreasing is_increasing = is_increasing_sequence(levels) is_decreasing = is_decreasing_sequence(levels) if not is_increasing and not is_decreasing: return False # Check that all adjacent levels differ by at least 1 and at most 3 for i in range(len(levels) - 1): diff = abs(levels[i + 1] - levels[i]) if diff < 1 or diff > 3: return False return True def is_increasing_sequence(numbers): for i in range(1, len(numbers)): if numbers[i] < numbers[i - 1]: return False return True def is_decreasing_sequence(numbers): for i in range(1, len(numbers)): if numbers[i] > numbers[i - 1]: return False return True if __name__ == "__main__": main()
Untuk penyelesaian yang kurang bertele-tele, kami boleh menggantikan bahagian dalam untuk gelung dengan pengubahsuaian dan penyemakan , seperti yang kami lakukan dengan LINQ dalam penyelesaian C#, seperti:
var reports = File.ReadAllLines("./input1.txt") .Select(x => x.Split(" ")) .ToList(); Part1(reports); void Part1(List<string[]> input) { var validReports = input .Select(report => report.Select(int.Parse).ToList()) .Count(IsValidReport); Console.WriteLine(validReports); } bool IsValidReport(List<int> levels) { // We don't care about the numbers, just wether going up or down, not both var isIncreasing = IsIncreasing(levels); var isDecreasing = IsDecreasing(levels); if (!isIncreasing && !isDecreasing) return false; // Check that all adjacent levels differ by at least 1 and at most 3 for (var i = 0; i < levels.Count - 1; i++) { var diff = Math.Abs(levels[i + 1] - levels[i]); if (diff is < 1 or > 3) { return false; } } return true; } bool IsIncreasing(List<int> numbers) { for (var i = 1; i < numbers.Count; i++) { if (numbers[i] < numbers[i - 1]) return false; } return true; } bool IsDecreasing(List<int> numbers) { for (var i = 1; i < numbers.Count; i++) { if (numbers[i] > numbers[i - 1]) return false; } return true; }
Tetapi saya rasa anda boleh bersetuju, kaedah verbose dengan pembolehubah bernama yang lebih bagus adalah lebih mudah dibaca.
Terima kasih kerana membaca, sertai saya lagi esok, dan seperti biasa hantarkan saya ikuti di twitter
Atas ialah kandungan terperinci Laporan AoC Day Red-Nosed (C# dan Python). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!