Today Solution was slighty more complex than the previous day warranting a little more code, but nevertheless was pretty straight forward.
Basic concepts of solution:
In order to be valid, the following conditions for Part 1 must be met:
We need to decide if the numbers are all increasing, or decreasing from one to the next.
the gap between the numbers can't be more than 3
Part 1
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 3) { return false; } } return true; } bool IsIncreasing(List<int> numbers) { for (var i = 1; i numbers) { for (var i = 1; i numbers[i - 1]) return false; } return true; } </int></int></string>
A simple explanation, is that we use LINQ parse the string numbers to integers before passing the report to our helper IsValidReport() method.
This method checks if all the numbers are either increasing or decreasing. This is done by comparing the ids with an ordered list, that will prove all the numbers are all going in one direction.
Once we know they're all in one direction (not the band) we can check if each number is within 3 numbers of each other. Using the Math.Abs() method, which returns the absolute number, helping us account for minus figures.
Note: an absolute number, is the number between the number and zero, i.e -5 and 5 would both return 5;
Part 2
For Part 2 we had an either slightly more complex instructions, but it sounds harder than it is.
The second part introduces the caveat of human error, with the basic concept that you need to know if you can remove any 1 item from the report and it will still be deemed a valid report.
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); } </string>
Here we're maximising the power of LINQ, parsing the string reports, as well as using it to modify the ints array. We modify by looping through the array and removing the current item at index, thus modifying the array of ints.
Once modified, we run the modified report through the validator. This can be done all in one go using the LINQ Select() method, combined with the Any() which will short circuit as soon as the condition is met (i.e as soon as a modified report is valid).
Why only check for a single valid modified report?
This is because it states if any one item can be removed then the report can be deemed valid. It doesn't say a particular item, so as soon as we find a matching item that when removed means the report is valid, we can stop looking at all the others.
We then increment the validReports counter, to keep track of our reports which are valid.
Here's my attempt at converting this to Python:
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 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 if __name__ == "__main__": main()
For a less verbose solution we could replace the Part 2 inner for loop with the modification and checking , like we did with LINQ in the C# solution, like so:
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 3) { return false; } } return true; } bool IsIncreasing(List<int> numbers) { for (var i = 1; i numbers) { for (var i = 1; i numbers[i - 1]) return false; } return true; } </int></int></string>
But I think you can agree, the verbose method with nicer named variables is much more readable.
Thanks for reading, join me again tomorrow, and as always drop me a follow on twitter
The above is the detailed content of AoC Day Red-Nosed Reports (C# and Python). For more information, please follow other related articles on the PHP Chinese website!

TomergelistsinPython,youcanusethe operator,extendmethod,listcomprehension,oritertools.chain,eachwithspecificadvantages:1)The operatorissimplebutlessefficientforlargelists;2)extendismemory-efficientbutmodifiestheoriginallist;3)listcomprehensionoffersf

In Python 3, two lists can be connected through a variety of methods: 1) Use operator, which is suitable for small lists, but is inefficient for large lists; 2) Use extend method, which is suitable for large lists, with high memory efficiency, but will modify the original list; 3) Use * operator, which is suitable for merging multiple lists, without modifying the original list; 4) Use itertools.chain, which is suitable for large data sets, with high memory efficiency.

Using the join() method is the most efficient way to connect strings from lists in Python. 1) Use the join() method to be efficient and easy to read. 2) The cycle uses operators inefficiently for large lists. 3) The combination of list comprehension and join() is suitable for scenarios that require conversion. 4) The reduce() method is suitable for other types of reductions, but is inefficient for string concatenation. The complete sentence ends.

PythonexecutionistheprocessoftransformingPythoncodeintoexecutableinstructions.1)Theinterpreterreadsthecode,convertingitintobytecode,whichthePythonVirtualMachine(PVM)executes.2)TheGlobalInterpreterLock(GIL)managesthreadexecution,potentiallylimitingmul

Key features of Python include: 1. The syntax is concise and easy to understand, suitable for beginners; 2. Dynamic type system, improving development speed; 3. Rich standard library, supporting multiple tasks; 4. Strong community and ecosystem, providing extensive support; 5. Interpretation, suitable for scripting and rapid prototyping; 6. Multi-paradigm support, suitable for various programming styles.

Python is an interpreted language, but it also includes the compilation process. 1) Python code is first compiled into bytecode. 2) Bytecode is interpreted and executed by Python virtual machine. 3) This hybrid mechanism makes Python both flexible and efficient, but not as fast as a fully compiled language.

Useaforloopwheniteratingoverasequenceorforaspecificnumberoftimes;useawhileloopwhencontinuinguntilaconditionismet.Forloopsareidealforknownsequences,whilewhileloopssuitsituationswithundeterminediterations.

Pythonloopscanleadtoerrorslikeinfiniteloops,modifyinglistsduringiteration,off-by-oneerrors,zero-indexingissues,andnestedloopinefficiencies.Toavoidthese:1)Use'i


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Zend Studio 13.0.1
Powerful PHP integrated development environment

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 English version
Recommended: Win version, supports code prompts!

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool
