This is really similar to Fibonacci Sequence problem. I understand the DP optimization with Fibonacci function using the for loop, but I'm having hard time to connect to this problem.
The recursion function I want to optimize is:
def cal(n):
if n <= 0:
return 1
else:
return cal(n-25)+cal(n-26)
Something like this may help:
(It's inspired by previous post)
from functools import cache
#cache
def cal(n):
if n <= 0:
return 1
else:
return cal(n-25) + cal(n-26)
print(cal(100))
The idea of a "for loop optimization" is that we calculate cal(0), cal(1), cal(2), ... consecutively. And when we want cal(n), we already have cal(n-25) and cal(n-26) stored in an array.
So, the following solution has linear complexity for non-negative n:
def cal(n):
mem = [1] # cal(0) is 1
for i in range(1, n + 1):
num = 1 if i - 25 < 0 else mem[i - 25]
num += 1 if i - 26 < 0 else mem[i - 26]
mem.append (num)
return mem[-1]
One can further optimize to make all the values cal(1), cal(2), ..., cal(n) globally available after calculating the last of them.
I am solving this homework of clean programming language;
The problem is we have a number of five digits and we want to check whether it's an odd palindrome or not.
I am stuck at the stage of dividing the number to five separate digits and perform a comparison with the original number, for the palindrome check. With Clean I can't loop over the number and check if it remains the same from the both sides, so I am looking for an alternative solution (Some mathematical operations).
Code block:
isOddPalindrome :: Int -> Bool
isOddPalindrome a
| isFive a <> 5 = abort("The number should be exactly five digits...")
| (/*==> Here should be the palindrome check <==*/) && (a rem 2 <> 0) = True
| otherwise = False
isFive :: Int -> Int
isFive n
| n / 10 == 0 = 1
= 1 + isFive(n / 10)
My idea is to take the number, append it's digits one by one to an empty list, then perform the reverse method on the list and check if it's the same number or not (Palindrome)
Your answer above doesn't have a stopping condition so it will result in stack overflow.
You could try this
numToList :: Int -> [Int]
numToList n
| n < 10 = [n]
= numToList (n/10) ++ [n rem 10]
Start = numToList 12345
and then like you mentioned in the answer, you can reverse it with the 'reverse' function and check if they are equal.
After hours of trying to figure out how to recursively add the digits of our number to an empty list, I did the following:
sepDigits :: Int [Int] -> [Int]
sepDigits n x = sepDigits (n/10) [n rem 10 : x]
Now I can easily check whether the reverse is equal to the initial list :) then the number is palindrome.
I am trying to find the smallest index containing the value i in a sorted array. If this i value is not present I want -1 to be returned. I am using a binary search recursive subroutine. The problem is that I can't really stop this recursion and I get lot of answers(one right and the rest wrong). And sometimes I get an error called "segmentation fault: 11" and I don't really get any results.
I've tried to delete this call random_number since I already have a sorted array in my main program, but it did not work.
program main
implicit none
integer, allocatable :: A(:)
real :: MAX_VALUE
integer :: i,j,n,s, low, high
real :: x
N= 10 !size of table
MAX_VALUE = 10
allocate(A(n))
s = 5 ! searched value
low = 1 ! lower limit
high = n ! highest limit
!generate random table of numbers (from 0 to 1000)
call Random_Seed
do i=1, N
call Random_Number(x) !returns random x >= 0 and <1
A(i)= anint(MAX_VALUE*x)
end do
call bubble(n,a)
print *,' '
write(*,10) (a(i),i=1,N)
10 format(10i6)
call bsearch(A,n,s,low,high)
deallocate(A)
end program main
The sort subroutine:
subroutine sort(p,q)
implicit none
integer(kind=4), intent(inout) :: p, q
integer(kind=4) :: temp
if (p>q) then
temp = p
p = q
q = temp
end if
return
end subroutine sort
The bubble subroutine:
subroutine bubble(n,arr)
implicit none
integer(kind=4), intent(inout) :: n
integer(kind=4), intent(inout) :: arr(n)
integer(kind=4) :: sorted(n)
integer :: i,j
do i=1, n
do j=n, i+1, -1
call sort(arr(j-1), arr(j))
end do
end do
return
end subroutine bubble
recursive subroutine bsearch(b,n,i,low,high)
implicit none
integer(kind=4) :: b(n)
integer(kind=4) :: low, high
integer(kind=4) :: i,j,x,idx,n
real(kind=4) :: r
idx = -1
call random_Number(r)
x = low + anint((high - low)*r)
if (b(x).lt.i) then
low = x + 1
call bsearch(b,n,i,low,high)
else if (b(x).gt.i) then
high = x - 1
call bsearch(b,n,i,low,high)
else
do j = low, high
if (b(j).eq.i) then
idx = j
exit
end if
end do
end if
! Stop if high = low
if (low.eq.high) then
return
end if
print*, i, 'found at index ', idx
return
end subroutine bsearch
The goal is to get the same results as my linear search. But I'am getting either of these answers.
Sorted table:
1 1 2 4 5 5 6 7 8 10
5 found at index 5
5 found at index -1
5 found at index -1
or if the value is not found
2 2 3 4 4 6 6 7 8 8
Segmentation fault: 11
There are a two issues causing your recursive search routine bsearch to either stop with unwanted output, or result in a segmentation fault. Simply following the execution logic of your program at the hand of the examples you provided, elucidate the matter:
1) value present and found, unwanted output
First, consider the first example where array b contains the value i=5 you are searching for (value and index pointed out with || in the first two lines of the code block below). Using the notation Rn to indicate the the n'th level of recursion, L and H for the lower- and upper bounds and x for the current index estimate, a given run of your code could look something like this:
b(x): 1 1 2 4 |5| 5 6 7 8 10
x: 1 2 3 4 |5| 6 7 8 9 10
R0: L x H
R1: Lx H
R2: L x H
5 found at index 5
5 found at index -1
5 found at index -1
In R0 and R1, the tests b(x).lt.i and b(x).gt.i in bsearch work as intended to reduce the search interval. In R2 the do-loop in the else branch is executed, idx is assigned the correct value and this is printed - as intended. However, a return statement is now encountered which will return control to the calling program unit - in this case that is first R1(!) where execution will resume after the if-else if-else block, thus printing a message to screen with the initial value of idx=-1. The same happens upon returning from R0 to the main program. This explains the (unwanted) output you see.
2) value not present, segmentation fault
Secondly, consider the example resulting in a segmentation fault. Using the same notation as before, a possible run could look like this:
b(x): 2 2 3 4 4 6 6 7 8 8
x: 1 2 3 4 5 6 7 8 9 10
R0: L x H
R1: L x H
R2: L x H
R3: LxH
R4: H xL
.
.
.
Segmentation fault: 11
In R0 to R2 the search interval is again reduced as intended. However, in R3 the logic fails. Since the search value i is not present in array b, one of the .lt. or .gt. tests will always evaluate to .true., meaning that the test for low .eq. high to terminate a search is never reached. From this point onwards, the logic is no longer valid (e.g. high can be smaller than low) and the code will continue deepening the level of recursion until the call stack gets too big and a segmentation fault occurs.
These explained the main logical flaws in the code. A possible inefficiency is the use of a do-loop to find the lowest index containing a searched for value. Consider a case where the value you are looking for is e.g. i=8, and that it appears in the last position in your array, as below. Assume further that by chance, the first guess for its position is x = high. This implies that your code will immediately branch to the do-loop, where in effect a linear search is done of very nearly the entire array, to find the final result idx=9. Although correct, the intended binary search rather becomes a linear search, which could result in reduced performance.
b(x): 2 2 3 4 4 6 6 7 |8| 8
x: 1 2 3 4 5 6 7 8 |9| 10
R0: L xH
8 found at index 9
Fixing the problems
At the very least, you should move the low .eq. high test to the start of the bsearch routine, so that recursion stops before invalid bounds can be defined (you then need an additional test to see if the search value was found or not). Also, notify about a successful search right after it occurs, i.e. after the equality test in your do-loop, or the additional test just mentioned. This still does not address the inefficiency of a possible linear search.
All taken into account, you are probably better off reading up on algorithms for finding a "leftmost" index (e.g. on Wikipedia or look at a tried and tested implementation - both examples here use iteration instead of recursion, perhaps another improvement, but the same principles apply) and adapt that to Fortran, which could look something like this (only showing new code, ...refer to existing code in your examples):
module mod_search
implicit none
contains
! Function that uses recursive binary search to look for `key` in an
! ordered `array`. Returns the array index of the leftmost occurrence
! of `key` if present in `array`, and -1 otherwise
function search_ordered (array, key) result (idx)
integer, intent(in) :: array(:)
integer, intent(in) :: key
integer :: idx
! find left most array index that could possibly hold `key`
idx = binary_search_left(1, size(array))
! if `key` is not found, return -1
if (array(idx) /= key) then
idx = -1
end if
contains
! function for recursive reduction of search interval
recursive function binary_search_left(low, high) result(idx)
integer, intent(in) :: low, high
integer :: idx
real :: r
if (high <= low ) then
! found lowest possible index where target could be
idx = low
else
! new guess
call random_number(r)
idx = low + floor((high - low)*r)
! alternative: idx = low + (high - low) / 2
if (array(idx) < key) then
! continue looking to the right of current guess
idx = binary_search_left(idx + 1, high)
else
! continue looking to the left of current guess (inclusive)
idx = binary_search_left(low, idx)
end if
end if
end function binary_search_left
end function search_ordered
! Move your routines into a module
subroutine sort(p,q)
...
end subroutine sort
subroutine bubble(n,arr)
...
end subroutine bubble
end module mod_search
! your main program
program main
use mod_search, only : search_ordered, sort, bubble ! <---- use routines from module like so
implicit none
...
! Replace your call to bsearch() with the following:
! call bsearch(A,n,s,low,high)
i = search_ordered(A, s)
if (i /= -1) then
print *, s, 'found at index ', i
else
print *, s, 'not found!'
end if
...
end program main
Finally, depending on your actual use case, you could also just consider using the Fortran intrinsic procedure minloc saving you the trouble of implementing all this functionality yourself. In this case, it can be done by making the following modification in your main program:
! i = search_ordered(a, s) ! <---- comment out this line
j = minloc(abs(a-s), dim=1) ! <---- replace with these two
i = merge(j, -1, a(j) == s)
where j returned from minloc will be the lowest index in the array a where s may be found, and merge is used to return j when a(j) == s and -1 otherwise.
I'm trying to write a basic function to take an integer and evaluate to a bool that will check whether the integer is a prime or not.
I've used an auxiliary function to keep track of the current divisor I'm testing, like so:
fun is_divisible(n : int, currentDivisor : int) =
if currentDivisor <= n - 1 then
n mod currentDivisor = 0 orelse is_divisible(n, currentDivisor + 1)
else
true;
fun is_prime(n : int) : bool =
if n = 2 then
true
else
not(is_divisible(n, 2));
It looks right to me but I test it on 9 and get false and then on 11 and get false as well.
Sorry for all the questions today and thanks!
The problem is that if your is_divisible reaches the last case it should return false because it means that all the iterated divisors have resulted in a remainder larger than zero except for the last one which is the number it self. So you should rename is_divisible and return false instead of true
I need to write a recursive function that returns the remainder of two numbers. Here's what I wrote:
def remainder(a,b):
if a==b:
return 0
else:
k=a-b
return a-b + remainder(b,a-k)
If we test remainder(5,3) the function will return 2 and it's correct but if we test remainder(15,3),
we'll get 12 and its false. I just don't know how to debug it.
You are missing a case: (when a < b)
def remainder(a,b):
if a<b: #trivial: remainder = a - b*0 = a
return a
else: #reduce the problem to a simple one
return remainder(a-b, b)
Test:
print remainder(15,3)
Output:
0
Here if you are lazy and don't want to write more than 2 lines:
def remainder(a,b):
return a if a < b else remainder(a-b, b)
It should be something like this :
def remainder(a,b):
if a<b:
return a
else:
return remainder(a-b,b)
You can do:
def remainder(a, b):
if a < b:
return a
return remainder(a - b, b)
Examples:
>>> remainder(15, 3)
0
>>> remainder(14, 3)
2
>>> remainder(13, 3)
1
If a < b then it means we're done: we know the result of the computation and we can return a. Otherwise we need to subtract b from a and we call remainder again recursively. This can then repeatedly continue until a is smaller than b. Once that happens the recursion stops (i.e., it won't call remainder again) but we're able to return the result.