# Challenge: Un-Recursive (Simple?)

• (4 Pages)
• 1
• 2
• 3
• 4

## 50 Replies - 23855 Views - Last Post: 18 September 2013 - 04:57 AM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 09:52 AM

andrewsw: Wrong.

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 01:03 PM

andrewsw, on 04 May 2013 - 05:48 PM, said:

Spoiler

Correction it does work. Sorry. />

I thought day of week didn't start on a Sun
UnixTime Epoch begin on a Thursday.
Also don't like that it use the DayOfWeek Enum as if was a value.
I think it is a little brittle, if the values are changed.

To me it has a lot of repetition and recalculation. Like the dte.DayOfWeek Mod 6 = 0.
Yes, it on a different instance of dte

```  Public Function AddWorkDays(ByVal dte As Date, ByVal x As Integer) As Date
Dim a = If(x < 0, -1, 1)
While x <> 0 Or (dte.DayOfWeek Mod 6 = 0)
x -= If(x = 0 Or (dte.DayOfWeek Mod 6 = 0), 0, a)
End While
Return dte
End Function

```

The following of mine is little heavy with the anonymous iterator lambda.
```Public  Function AddWorkDays(d As Date, wd As integer) As Date
Return (Iterator  Function()
Dim a = If(wd<0,-1,1)
While True
If d.DayOfWeek.IsAnyOfThese({DayOfWeek.Saturday, DayOfWeek.Sunday}) Then
Else
Yield d
If wd<>0 Then
wd -= a
Else
Exit While
End If
End If
End While
End Function)().Last
End Function

```

Also don't like that it uses While True there a chance of infinite looping.
Don't know if a theorem proofer would mark it a safe to use cos if converges
And the calculation of the next date is done twice.

So this is my current implementation.
```  Public Function AddWorkDays_B( InitialDate As Date,
WorkingDays As Integer
) As Date
REM --- Variable used ---
Dim FromDateCalculated   = InitialDate
Dim Delta                = If(WorkingDays < 0, -1, 1)
Dim CalculationsAreDone  = False
REM --- Lambda Functions ---
Dim IsNonWorkDay         = Function(ds As Date) ds.DayOfWeek.IsAnyOfThese({DayOfWeek.Saturday, DayOfWeek.Sunday})
Dim DateForNextIteration = Function(ds As Date) ds.AddDays(Delta)
REM -- Start of Calculation Iteration ---
Do
If IsNonWorkDay ( FromDateCalculated ) then
FromDateCalculated = DateForNextIteration(FromDateCalculated)
ElseIf WorkingDays <> 0 Then
FromDateCalculated = DateForNextIteration(FromDateCalculated)
REM --- Decrement Working Days by the Delta
WorkingDays -= Delta
Else
CalculationsAreDone = True
End If
Loop Until CalculationsAreDone
Return FromDateCalculated
End Function

```

The thing the slightly bugs be is this
```   If IsNonWorkDay ( FromDateCalculated ) then
FromDateCalculated = DateForNextIteration(FromDateCalculated)
ElseIf WorkingDays <> 0 Then
FromDateCalculated = DateForNextIteration(FromDateCalculated)
REM --- Decrement Working Days by the Delta
WorkingDays -= Delta

```

The two branches are almost identical expect for WorkingDays -= Delta .

Don't repeat yourself senses tingling.

This post has been edited by AdamSpeight2008: 04 May 2013 - 01:30 PM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:02 PM

Using the following Iterator to yield dates.
```  Public Iterator Function YieldDates(d As Date, inc As Boolean) As IEnumerable(of  Date)
Dim a = If(inc,-1,1)
While True
Yield d
end While
End Function

```

Then use LINQ.
```  Public  Function AddWorkdays_C(d As date, wd As Integer) As Date
Return ( From x in YieldDates( d, wd<0 )
Where x.DayOfWeek <> DayOfWeek.Saturday
Where x.DayOfWeek <> DayOfWeek.Sunday
Skip Math.Abs(wd)
Take 1 ).FirstOrDefault
End Function

```

Which I like a lot.

This post has been edited by AdamSpeight2008: 04 May 2013 - 02:04 PM

### #19 andrewsw

• blow up my boots

Reputation: 6524
• Posts: 26,405
• Joined: 12-December 12

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:09 PM

What no rep

In VBA Sunday is 1 and Saturday 7, and if we use the older Weekday() function we can specify what day the week starts on.

However, I hope that we could rely on the weekdays enumeration. Would MS have the gall to change it (again)?!

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:20 PM

During this I discovered something which is counter-intuitive (to me).
```Do
If conditon Then
Continue Do
End If
Loop Until exit_condition

```

You'd think it'll jump back to Do but it does not it jumps to the Loop Until. Doh?

This post has been edited by AdamSpeight2008: 04 May 2013 - 02:20 PM

### #21 andrewsw

• blow up my boots

Reputation: 6524
• Posts: 26,405
• Joined: 12-December 12

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:26 PM

AdamSpeight2008, on 04 May 2013 - 09:20 PM, said:

During this I discovered something which is counter-intuitive (to me).
```Do
If conditon Then
Continue Do
End If
Loop Until exit_condition

```

You'd think it'll jump back to Do but it does not it jumps to the Loop Until. Doh?

That makes sense to me, otherwise you would use Exit Do.

This (final) version is neater:

```    Public Function AddWorkDays(ByVal dte As Date, ByVal x As Integer) As Date
Dim a As Integer = If(x < 0, -1, 1)
Dim weekend = {DayOfWeek.Saturday, DayOfWeek.Sunday}
While x <> 0 Or weekend.Contains(dte.DayOfWeek)
x -= If(x = 0 Or weekend.Contains(dte.DayOfWeek), 0, a)
End While
Return dte
End Function
```

Added: In fact, it could be easily modified to incorporate an array of bank holidays.

This post has been edited by andrewsw: 04 May 2013 - 02:35 PM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:34 PM

Still contains that annoy (to me) repetition, of the conditions checks.
The following has very little repetition, which appeases the don't repeat yourself feelings.

```  Public Function AddWorkDays_D(d As Date, x As Integer) As Date
Dim a = If(x<0,-1,1)
Beginning:
If (d.DayOfWeek = DayOfWeek.Saturday) OrElse (d.DayOfWeek = DayOfWeek.Sunday)  Then GoTo NextDate
If x <> 0 Then GoTo ChangeX
Return D
ChangeX:
x -= a
NextDate:
GoTo Beginning
End Function

```

Any issues with that one?

### #23 andrewsw

• blow up my boots

Reputation: 6524
• Posts: 26,405
• Joined: 12-December 12

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:40 PM

Erm, GoTo?! Three labels (spaghetti anyone?)

Seems a lot of effort to go through to avoid a minor piece of repetition(?).

This post has been edited by andrewsw: 04 May 2013 - 02:41 PM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:46 PM

andrewsw, on 04 May 2013 - 10:26 PM, said:

AdamSpeight2008, on 04 May 2013 - 09:20 PM, said:

During this I discovered something which is counter-intuitive (to me).
```Do
If conditon Then
Continue Do
End If
Loop Until exit_condition

```

You'd think it'll jump back to Do but it does not it jumps to the Loop Until. Doh?

That makes sense to me, otherwise you would use Exit Do.

If it work the way I thought it would, the following would be a valid entry.
```Do
If d.DayOfWeek = DayOfWeek.Saturday OrElse d.DayOfWeek = Sunday Then
Continue Do
Else If x<> 0 Then
x -= a
Continue Do
End If
Loop Until x = 0

```

That be method localized spaghetti.

What about adding in checks for if the date d is on of min or max values for a date?
I'd only have to have in one place, not two.

This post has been edited by AdamSpeight2008: 04 May 2013 - 02:40 PM

### #25 andrewsw

• blow up my boots

Reputation: 6524
• Posts: 26,405
• Joined: 12-December 12

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 02:46 PM

You could introduce a boolean flag:

```Loop Until x = 0 And Not goAgain
```

(or make x nullable )

This post has been edited by andrewsw: 04 May 2013 - 02:50 PM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 03:18 PM

Likes so.
```  Dim a = If(x<0, -1, 1)
Do
Dim GoAgain = True
If (d.DayOfWeek = DayOfWeek.Saturday) OrElse (d.DayOfWeek = DayOfWeek.Sunday) Then
Else If x <> 0 Then
x -= a
Else
GoAgain = False
End If
Loop Until (x = 0) AndAlso Not (GoAgain)
Return D

```

Is not valid syntax the GoAgain isn't in scope.
```  Public Function AddWorkDays_E(d As Date, x As Integer) As Date
Dim a = If(x<0, -1, 1)
Dim GoAgain As Boolean
Do
GoAgain = True
If (d.DayOfWeek = DayOfWeek.Saturday) OrElse (d.DayOfWeek = DayOfWeek.Sunday) Then
Else If x <> 0 Then
x -= a
Else
GoAgain = False
End If
Loop Until (x = 0) AndAlso Not (GoAgain)
Return D
End Function

```

then it could be postulated you don't need x = 0
``` Public Function AddWorkDays_F(d As Date, x As Integer) As Date
Dim a = If(x<0, -1, 1)
Dim GoAgain As Boolean
Do
GoAgain = True
If (d.DayOfWeek = DayOfWeek.Saturday) OrElse (d.DayOfWeek = DayOfWeek.Sunday) Then
Else If x <> 0 Then
x -= a
Else
GoAgain = False
End If
Loop While GoAgain
Return D
End Function

```

I'm a advocate of the style, that they should only be a single condition for conditional part of looping constructs.
Multiple conditions suggest it need to be simplified. And stylistically it look complex and untidy.

### #27 andrewsw

• blow up my boots

Reputation: 6524
• Posts: 26,405
• Joined: 12-December 12

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 03:27 PM

You don't need to keep resetting GoAgain to True (and I still like Contains() />).

```    Public Function AddWorkDays_F(ByVal d As Date, ByVal x As Integer) As Date
Dim a = If(x < 0, -1, 1)
Dim GoAgain As Boolean = True
Do
If {DayOfWeek.Saturday, DayOfWeek.Sunday}.Contains(d.DayOfWeek) Then
ElseIf x <> 0 Then
x -= a
Else
GoAgain = False
End If
Loop While GoAgain
Return D
End Function
```

This post has been edited by andrewsw: 04 May 2013 - 03:34 PM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 03:36 PM

.Contains is backwards when being read, especially if is a single value.
So I like to use the .IsAnyOfThese extension method
```  <Extension>
Function IsAnyOfThese(Of T As IComparable)(Value As T, These As IEnumerable(Of T)) As Boolean
Return These.Any(Function(x) x.CompareTo(Value) = 0)
End Function

```

As it so much easier to read and understand when look at the code.
```If d.DayOfWeek.IsAnyOfThese( { Saturday, Sunday } ) Then

```

This post has been edited by AdamSpeight2008: 04 May 2013 - 03:45 PM

### #29 andrewsw

• blow up my boots

Reputation: 6524
• Posts: 26,405
• Joined: 12-December 12

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 03:38 PM

Yes, Contains() is backwards, he,he!

Added: What happeneded to IN() ? I wouldn't mind having this as an extension method. I suppose I could just replace IsAnyOfThese with In in the above code.

This post has been edited by andrewsw: 04 May 2013 - 03:47 PM

• MrCupOfT

Reputation: 2298
• Posts: 9,535
• Joined: 29-May 08

## Re: Challenge: Un-Recursive (Simple?)

Posted 04 May 2013 - 03:59 PM

Using Exts.Dates makes it a little better.
```  Public Function AddWorkDays_E(d As Date, x As Integer) As Date
Dim a = If(x<0, -1, 1)
Dim GoAgain =True
Do
If d.IsA(Saturday) Or d.IsA(Sunday) Then
Else If x <> 0 Then
x -= a
Else
GoAgain = False
End If
Loop While GoAgain
Return D
End Function

```

May have to add .IsAnyOfThese to a Exts package? thou I'm sure it I had it anyways.