0

Without using the Array.Sort function, I am supposed to read numbers from two files (individually sorted in least-to-greatest order) and consolidate them into a list box in least-to-greatest order. I thought this was an elegant solution to the problem, but there is a single bug I can't seem to stamp out.

It's difficult to explain without you having seen it, so here's the code I have (no error handlers at the moment):

Private Sub btnMerge_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMerge.Click
    'read the files entered in the text boxes
    Dim file1() As String = IO.File.ReadAllLines(txtFile1.Text)
    Dim file2() As String = IO.File.ReadAllLines(txtFile2.Text)
    'simplify removal of the smallest item of the array.  
    '(the last item because the values in each file are sorted)
    Array.Reverse(file1)
    Array.Reverse(file2)

    While file1.Length > 0 Or file2.Length > 0 'as long as there are numbers left in either array
        If file1.Length And file2.Length Then 'numbers in both arrays
            Debug.WriteLine(file1.Last & " vs " & file2.Last)
            If CInt(file1.Last) < CInt(file2.Last) Then
                lstOutput.Items.Add(file1.Last)
                ReDim Preserve file1(file1.Length - 2) 'remove last (smallest) number
            Else
                lstOutput.Items.Add(file2.Last)
                ReDim Preserve file2(file2.Length - 2) 'remove last (smallest) number
            End If
        ElseIf file1.Length Then 'file2 is empty.  comparison of last values will throw an error
            Debug.WriteLine(file1.Last & " vs " & "Nothing")
            lstOutput.Items.Add(file1.Last)
            ReDim Preserve file1(file1.Length - 2) 'remove last (smallest) number
        ElseIf file2.Length Then 'file1 is empty.  comparison of last values will throw an error
            Debug.WriteLine("Nothing" & " vs " & file2.Last)
            lstOutput.Items.Add(file2.Last)
            ReDim Preserve file2(file2.Length - 2) 'remove last (smallest) number
        End If
    End While
End Sub

File1.dat:

12
23
34
45
46
52

File2.dat:

4
5
10
20
25

The output in lstOutput is this:

4
5
10
12
23
34 <-- what??
20
25
45
46
52

And the output in the debug log is this:

12 vs 4

12 vs 5

12 vs 10

12 vs 20

23 vs Nothing <-- what??

34 vs Nothing <-- what??

45 vs 20

45 vs 25

45 vs Nothing

46 vs Nothing

52 vs Nothing

As you can see, the algorithm performs perfectly until the fifth comparison and after the sixth. But why is 34 being inserted into the list box before 20? Where did those two "vs Nothing"s in the middle of the debug log come from? file2.Length evaluating to False -- twice in a row -- when it is actually 2 (confirmed via breakpoints)!

Note: I am fully aware that the use of ReDim Preserve is to be discouraged. Only comment on it if you have reason to believe it is the problem.

Proxy
  • 1,824
  • 1
  • 16
  • 27
  • Would you be open to a different solution or are you looking to find out why yours isn't working? – John Bustos Feb 13 '14 at 19:36
  • 1
    This sounds like homework, where the objective of the homework is to have you write your own sort function. We could fix this code for you such that it produces the correct output, but you'll likely still fail the assignment if you don't write a sort method of your own. – Joel Coehoorn Feb 13 '14 at 19:50
  • Have a look at how this programmer did it... Much more efficient in my opinion: http://stackoverflow.com/questions/5958169/how-to-merge-two-sorted-arrays-into-a-sorted-array – John Bustos Feb 13 '14 at 20:03
  • @JohnBustos The former would also help, but I'm looking for the latter. – Proxy Feb 13 '14 at 20:25
  • @JoelCoehoorn Of course it's homework. That doesn't make it an invalid question. In StackOverflow, homework questions are only invalid if you ask for a solution in its entirety. "Sounds like homework" is just an excuse to not answer. – Proxy Feb 13 '14 at 20:26
  • @Proxy I didn't vote to close it. I'm just warning you: you may want to try a different approach to appease your professor. – Joel Coehoorn Feb 13 '14 at 20:43

2 Answers2

2

Your IF is not correct, like you wrote it, it's doing a bitwise operation. You should have.

If file1.Length > 0 And file2.Length > 0 Then 

Personally, instead of a reverse/redim I would just keep an index of the current position of each array.

the_lotus
  • 12,668
  • 3
  • 36
  • 53
  • Got it. 101 (5) and 010 (2) is false; so is 100 and 010. Thank you. – Proxy Feb 13 '14 at 20:32
  • You should use AndAlso so you get short circuiting as well, although it doesn't make a difference in this case. It's a good habit to get into though. – Chris Dunaway Feb 13 '14 at 22:47
0

I can get this down to almost a one-liner:

Private Sub btnMerge_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMerge.Click
    For Each i As Integer In IO.File.ReadLines(txtFile1.Text).Concat(IO.File.ReadLines(txtFile2.Text)).OrderBy(Function(s) Convert.ToInt32(s)).Distinct()
        lstOutput.Items.Add(i)
    Next 
End Sub

But, so that it's a bit more readable:

Private Sub btnMerge_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMerge.Click
    Dim numbers = File.ReadLines(txtFile1.Text) _ 
         .Concat(IO.File.ReadLines(txtFile2.Text)) 
         .Select(Function(s) Convert.ToInt32(s))
         .OrderBy(Function(i) i) _
         .Distinct()

    For Each i As Integer In numbers
        lstOutput.Items.Add(i)
    Next 
End Sub
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794