Reputation:
I'm new to Julia Language and, by now, trying to learn by myself using the book "Julia Bit-by-Bit: Programming for Beginners" wrote by Noel Kalicharan. Right now I'm trapped in Problem 16 - Exercises 4, which asks for a solution using 'for', 'if', 'while' to the next problem:
You are given a file containing an unknown amount of numbers. Each number is one of the numbers 1 to 9. A number can appear zero or more times and can appear anywhere in the file. Some sample data are:
5 3 7 7 7 4 3 3 2 2 2 6 7 4 7 7
2 2 9 6 6 6 6 6 8 5 5 3 7 9 9 9
Write a program to read the data once and print the number which appears the most in consecutive positions and the number of times it appears. Ignore the possibility of a tie. For the above data, output should be 6 5.
Can anyone help me?
Thanks!
Upvotes: 0
Views: 216
Reputation:
I just solved it. I appreciate your to time for answering my question. In your answers there is some code that I'm not familiar yet. So I take these days to think and try to figure it out using the tools that the book provide me.
function exercise16()
inn = open("input.txt", "r")
n = 0
maxn = 0
maxdigit = ""
while (eData = readline(inn)) != ""
eData = split(eData)
for i in "123456789"
while true
n += 1
if i != eData
break
end
end
if n > maxn
maxn = n
maxdigit = i
n = 0
continue
end
end
end
print("$maxdigit $maxn")
close(inn)
end
Upvotes: 0
Reputation: 5559
This turned out to be harder than I initially thought, so I gave it a try. First you read the contents of the file containing the digits and remove spaces. Then, initialize the frequency of repetition to zeros and start from second digit. If a digit is equal to the previous one, increment its count and continue until all digits were compared. Finally return the digit with the maximum count and its count.
function calc_freq(file_path)
freq = Dict(zip('0':'9',fill(0,10))) # digits and their frequencies
str = read(file_path, String) # read whole file as String
str = filter(!isspace, str) # remove possible spaces
i = 1
c = str[1]
while i < length(str)
count = 1
for j = i+1:length(str)
if str[j] == c
count += 1
else
break
end
end
if count > 1
freq[c] = max(count, freq[c])
end
i += count
c = str[i]
end
maxval = maximum(values(freq))
for (k,v) in freq
v == maxval && return (k,v)
end
end
If applied on your example input, this outputs:
('6', 5)
Edit: Inspired by @SundarR's answer, I optimized my original version so that it keeps track of only one longest repetitive sequence instead of all the sequences of all ten digits, which was not required by the question. This version is 40X faster than @SundarR's version. The price here is higher memory usage, but for 40X speed difference, that's a good price to pay.
function calc_freq_fast(file_path)
str = read(file_path, String) # read file contents as String
str = filter(!isspace, str) # remove possible spaces
digit = maxdigit = '\0'
count = maxcount = 0
for ch in str
if ch == digit
count += 1
else
digit = ch
count = 1
end
if count > maxcount
maxdigit, maxcount = digit, count
end
end
maxdigit, maxcount
end
This is how the two methods compare on a 100k digits file:
@btime getmaxrepeater("file.txt") # 19.952 ms (11 allocations: 680 bytes)
@btime calc_freq_fast("file.txt") # 495.600 μs (15 allocations: 391.66 KiB)
Upvotes: 0
Reputation: 14695
Since the question says "a file containing an unknown amount of numbers", I wanted to avoid assuming that the whole file is small enough to be read into memory. So instead, this code reads only a single character at a time, skipping past any non-numeric characters in the file.
"""
getmaxrepeater([filename::String])
Given a file, find the digit that repeats the most consecutive times in it.
Returns the most repetitive digit (as a Char) and the number of times it
repeats. If no numeric characters are found in the file, returns ('\0', 0).
"""
function getmaxrepeater(fname = joinpath(@__DIR__, "data/repeatingnums.txt"))
currcount = maxcount = 0
currdig = maxdig = '\0'
f = open(fname)
while true
# Skip any characters that are not one of the digits we want
skipchars(!isnumeric, f)
# Try to read a single character (a digit) from the file
c = try
read(f, Char)
catch e
# End-Of-File (EOFError) is expected when file contents are done, but any
# other error should be rethrown and handled by Julia
e isa EOFError || rethrow()
# If it is the expected EOFError, close the filehandle and return the results
close(f)
return (maxdig, maxcount)
end
# If the digit we just read is a repeat of the previous one, just increase its count
if c == currdig
currcount += 1
else # otherwise, start counting the new one
currdig = c
currcount = 1
end
# Update the maxcount (and the corresponding digit maxdig) every time the
# old maxcount is exceeded
if currcount > maxcount
maxdig, maxcount = currdig, currcount
end
end
end
julia> getmaxrepeater("./data/repeatingnums.txt")
('6', 5)
Upvotes: 0