Reputation: 11
It get a file as a parameter and I need the sum of the even and odd numbers in the even and odd lines of the file
Input:
1 2 3 4 5
2 3 9 5
4 6 1
6 3 1 2 4
Output:
Sum of odd numbers:(1+3+5+1)=10
Sum of even numbers:(2+6+2+4)=12
I tried with foreach and without it, but I don't know how to convert strings from a file to an integer and put it an array
Upvotes: 0
Views: 5175
Reputation: 60518
I guess I'll post my solution to this question too, didn't want to at the moment because I thought it was homework but since there are already 2 answers and since I did already had the code...
The code is very similar to Theo's answer.
using namespace System.Collections.Generic
using namespace System.Linq
$i = $false
$oddArray = [list[int]]::new()
$evenArray = [list[int]]::new()
foreach($line in $array) {
$numbers = $line -split '\s+'
if($i = -not $i) {
# Odd Lines
foreach($number in $numbers) {
# If this number is Odd
if($number % 2) {
$oddArray.Add($number)
}
}
continue
}
#Even Lines
foreach($number in $numbers) {
# If this number is even
if(-not ($number % 2)) {
$evenArray.Add($number)
}
}
}
[string]::Format(
"Sum of odd numbers: ({0}) = {1}",
($oddArray -join ' + '),
[Enumerable]::Sum($oddArray)
)
[string]::Format(
"Sum of even numbers: ({0}) = {1}",
($evenArray -join ' + '),
[Enumerable]::Sum($evenArray)
)
Upvotes: 1
Reputation: 1
Looking at others I felt the string generation could be simplified. Also use (abuse?) of Powershell dynamic casting. A bit of google research including random other pages provided inspiration and useful bits.
#read input, split on any whitespace
$inputFile = (Get-Content "C:\temp\numbers.txt") -split "\s"
#generate odds and evens arrays.
$inputFile | foreach{ if($_ % 2 -eq 0) {$evens += $_} else{$odds += $_}}
#make output strings
"Sum of odd numbers:(" + ($odds -join '+') + ")=" + (($odds|Measure-Object -Sum).Sum)
"Sum of even numbers:(" + ($evens -join '+') + ")=" + (($evens|Measure-Object -Sum).Sum)
Upvotes: 0
Reputation: 7087
I wrote this yesterday, but questioning if the question was homework, I initially didn't want to post. That said, since others are working on it, I figured I should go ahead and share.
$Numbers = @( Get-Content 'C:\temp\numbers.txt' )
$EvenOdd = @{ 0 = 'even'; 1 = 'odd' }
For( $i = 0; $i -lt $Numbers.Count; ++$i )
{
$LineOdd = $i % 2
$Sum =
$Numbers[$i].Trim() -Split "\s+" |
Where-Object{ $_ % 2 -eq $LineOdd } |
Measure-Object -Sum |
Select-Object -ExpandProperty Sum
"Line {0} : Sum of {1} numbers:({2})={3}" -f $i, ($EvenOdd[$LineOdd]), ($NumberArray -Join '+'), $Sum
}
Result:
Line 0 : Sum of even numbers:(2+4)=6
Line 1 : Sum of odd numbers:(3+9+5)=17
Line 2 : Sum of even numbers:(4+6)=10
Line 3 : Sum of odd numbers:(3+1)=4
To consider the 1st line Line# 1 a few minor adjustments:
$Numbers = @( Get-Content 'C:\temp\numbers.txt' )
$EvenOdd = @{ 0 = 'even'; 1 = 'odd' }
For( $i = 1; $i -le $Numbers.Count; ++$i )
{
$LineOdd = $i % 2
$Sum =
$Numbers[$i-1] -Split "\s+" |
Where-Object{ $_ % 2 -eq $LineOdd } |
Measure-Object -Sum |
Select-Object -ExpandProperty Sum
"Line {0} : Sum of {1} numbers:({2})={3}" -f $i, ($EvenOdd[$LineOdd]), ($NumberArray -Join '+'), $Sum
}
Note: I was originally splitting on a regular space. I took the split on whitespace idea and the .Trim()
from Theo's example. I didn't bother casting to [int]
.
Note: These examples aren't comparable to Theo's answer. It's clear that we interpreted the question differently. If I have time I'll work the other interpretation.
Alternate sums all numbers from odd & even lines respectively:
$Numbers = @( Get-Content 'C:\temp\numbers.txt' )
$EvenNumbers = [System.Collections.Generic.List[int]]::new()
$OddNumbers = [System.Collections.Generic.List[int]]::new()
For( $i = 1; $i -le $Numbers.Count; ++$i )
{
$LineOdd = $i % 2
$NumberHash =
$Numbers[$i-1].Trim() -Split "\s+" |
Group-Object { $_ % 2 } -AsHashTable
Switch ($LineOdd)
{
0 { $NumberHash[0].foreach( { $EvenNumbers.Add($_) } ); Break }
1 { $NumberHash[1].foreach( { $OddNumbers.Add($_) } ); Break }
}
}
$SumEven = ($EvenNumbers | Measure-Object -Sum).Sum
$SumOdd = ($OddNumbers | Measure-Object -Sum ).Sum
"Sum of odd lines : {0}{1}" -f "($($OddNumbers -join '+'))=",$SumOdd
"Sum of even lines : {0}{1}" -f "($($EvenNumbers -join '+'))=", $SumEven
In retrospect this would work just as well with a ForEach-Object{}
in place of Group-Object
& Switch
, so I added another example:
$Numbers = @( Get-Content 'C:\temp\numbers.txt' )
$EvenNumbers = [System.Collections.Generic.List[int]]::new()
$OddNumbers = [System.Collections.Generic.List[int]]::new()
For( $i = 1; $i -le $Numbers.Count; ++$i )
{
$LineOdd = $i % 2
$Numbers[$i-1].Trim() -Split "\s+" |
ForEach-Object{
If( !$LineOdd -and $_ % 2 -eq 0 ) {
$EvenNumbers.Add($_)
}
Elseif( $LineOdd -and $_ % 2 -eq 1 ) {
$OddNumbers.Add($_)
}
}
}
$SumEven = ($EvenNumbers | Measure-Object -Sum).Sum
$SumOdd = ($OddNumbers | Measure-Object -Sum ).Sum
"Sum of odd lines : {0}{1}" -f "($($OddNumbers -join '+'))=",$SumOdd
"Sum of even lines : {0}{1}" -f "($($EvenNumbers -join '+'))=", $SumEven
And a more efficient & eloquent version of that last one:
$Numbers = @( Get-Content 'C:\temp\numbers.txt' )
$Sum = @{
0 = [System.Collections.Generic.List[int]]::new()
1 = [System.Collections.Generic.List[int]]::new()
}
For( $i = 1; $i -le $Numbers.Count; ++$i )
{
$LineOdd = $i % 2
$Numbers[$i-1].Trim() -Split "\s+" |
ForEach-Object{
If( $_ % 2 -eq $LineOdd ) {
$Sum[$LineOdd].Add($_)
}
}
}
$SumOdd = ($Sum[1] | Measure-Object -Sum).Sum
$SumEven = ($Sum[0] | Measure-Object -Sum).Sum
"Sum of odd lines : {0}{1}" -f "($($Sum[0] -join '+'))=", $SumOdd
"Sum of even lines : {0}{1}" -f "($($Sum[1] -join '+'))=", $SumEven
So, this is an improvement because it only needs a single If
statement inside the loop. It also prevents a significant number of modulus calculations. In the previous sample I had an If/ElseIf
ergo every time the ElseIf
fires a second modulus calculation would occur. granted, I could've pre-calculated a variable, but that wouldn't have completely removed the Else...
. Instead by storing the collections in a hash a simple comparison is all that's needed to know which collection to append.
Note: The last 3 examples start at Line 1 and consider line 1 odd. As opposed to line 0...
Upvotes: 1
Reputation: 61158
This is one way of doing this.
The code below uses a Here-String dummy representation of the input file, but in real life you would use
$fileIn = Get-Content -Path 'Path\To\The\FileWithNumbers.txt'
$fileIn = @"
1 2 3 4 5
2 3 9 5
4 6 1
6 3 1 2 4
"@ -split '\r?\n'
$oddLine = $true # first line is an odd line
$oddTotal, $evenTotal = 0 # create two variables to total the numbers
foreach ($line in $fileIn) {
[int[]]$numbers = $line.Trim() -split '\s+' # split on whitespace(s) and cast to [int]
foreach ($n in $numbers) {
if ($oddLine) {
if ($n % 2) { $oddTotal += $n }
}
else {
if (($n % 2) -eq 0) { $evenTotal += $n }
}
}
$oddLine = !$oddLine # toggle odd and even line
}
"Sum of odd numbers in odd lines: $oddTotal"
"Sum of even numbers in even lines: $evenTotal"
Result:
Sum of odd numbers in odd lines: 10
Sum of even numbers in even lines: 14
P.S. there's a mistake in your example output: 2+6+2+4
equals 14, not 12 ;)
If your output also needs to show the numbers added, you can do something like this:
$oddLine = $true # first line is an odd line
# create two collection objects to gather all the numbers
$oddNumbers = [System.Collections.Generic.List[int]]::new()
$evenNumbers = [System.Collections.Generic.List[int]]::new()
foreach ($line in $fileIn) {
[int[]]$numbers = $line.Trim() -split '\s+' # split on whitespace(s) and cast to [int]
foreach ($n in $numbers) {
if ($oddLine) {
if ($n % 2) { $oddNumbers.Add($n) }
}
else {
if (($n % 2) -eq 0) { $evenNumbers.Add($n) }
}
}
$oddLine = !$oddLine # toggle odd and even line
}
# calculate the totals from the lists
$oddTotal = ($oddNumbers | Measure-Object -Sum).Sum
$evenTotal = ($evenNumbers | Measure-Object -Sum).Sum
"Sum of odd numbers in odd lines: $oddTotal ($($oddNumbers -join '+'))"
"Sum of even numbers in even lines: $evenTotal ($($evenNumbers -join '+'))"
Result:
Sum of odd numbers in odd lines: 10 (1+3+5+1)
Sum of even numbers in even lines: 14 (2+6+2+4)
Upvotes: 1