Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
27416 Discussions

Assigning int to string causes program to crash

MFerguson
Beginner
421 Views

I'm working on a ProjectEuler problem, number 36 to be exact.

I'm having an issue when converting an integer to a string in order to send them to my palindrome(string) function which returns a logical

I have played around with different syntaxes for the character array definition for the string,  but the current code below is the only way I could get it to compile.

 

---START CODE---

program Euler36

implicit none
integer :: time_start, time_finish, clock_finish, solution = 0, i
character, allocatable :: s1(:)
call SYSTEM_CLOCK(time_start)

do i = 1,1000000
write (s1,'(I0)') i
print*,s1
if (palindrome(s1)) then
write(s1,'(B0)') i
print*,s1
if (palindrome(s1)) then
solution = solution + 1
end if
end if
end do

call SYSTEM_CLOCK(time_finish)
clock_finish = time_finish - time_start
write (*,"(A10,I10,//,A21,I5,A14)") "Solution: ",solution,"Program completed in ",clock_finish," milliseconds."

contains

logical function palindrome(str)
character, allocatable :: str(:)
integer :: i

do i = 0,len(str)/2

if (str(i+1) /= str((len(str))-i)) then
palindrome = .false.
return
end if
end do
palindrome = .true.
return
end

end program Euler36

---END CODE---

The output to command line states "Fortran runtime error: End of record" and then prints backtrace hexadecimal addresses.

The error occurs on line "write (s1,'(I0)') i" which from multiple tutorials I've seen is the "correct" way to do this.

How can I properly assign the integers to string variables such that they can be sent correctly to my palindrome(string) function?

0 Kudos
1 Solution
andrew_4619
Honored Contributor II
413 Views

You cannot allocate a string with a write.  You could:

character(:), allocatable :: s1
character(10) :: s10 ! 10 chars is big enough

write (s10,'(I0)') i
s1 = trim(s10) ! allocates s1 to exact length

View solution in original post

6 Replies
andrew_4619
Honored Contributor II
414 Views

You cannot allocate a string with a write.  You could:

character(:), allocatable :: s1
character(10) :: s10 ! 10 chars is big enough

write (s10,'(I0)') i
s1 = trim(s10) ! allocates s1 to exact length
JohnNichols
Valued Contributor II
378 Views

A brief look at the Pure Math behind the problem suggests that the decimal and the binary palindromes each have a numerical pattern, the decimal based on the series, 1, 10, 11, 110, etc..  The binary based on 2 and 5.  

You should be able to construct a simple set of 3 do loops that will cover the range 0 to 999,999 as 1,000,000 can never be a palindrome.  

You break the numbers into even and odd lengths and then do your comparison, starting from the outside, as once you find a potential decimal one then the next length has none, the length varies based on the number of digits.  But 11 is a potential and then the next one is 22, 33 etc.. there is no need to search in between.  There is no reason to omit zero as it has no leading zeros, it is a good number. 

A similar exercise in the binary should yield the final set. 

So , 0, 1, 2, 3, 4, 5, 6, 7, 8 , 9 are palindromes, but 10 is not, 11 is - but in binary the 0, 1, 11, 101, 111, 1001, 1111 etc. match 0, 1, 3, 5, etc.. 

At the next stage, 11, 22, 33, 44, 55, 66 ,77, etc.  then 101, 111, 121, 131, 141, 151,161,171,181, 191 - they always come in groups of 9 below 1000. I think there are 9 * 11 = 99, below 1,000.  

My old Pure math professor once said, it is correct but it is not elegant.  

 

My guess is about 100000 potential palindromes in the first pass and it comes down from there, you would need three passes as there are 3 sets of doubles in 999999. 

 

Just a thought.  But you can assemble them in a 6 unit block and then drop all the zeros. 

000000

000100

000200

000300

000400

000500

000600

000700

000800

000900

001100

002200

003300

...

009900

001010

001110

001210 

...

As well any ending in 2, 4, 6, or 8 is likely to generate a 10 ending or similar.  

So there are about I think 40 to 50 below 1000 that need to be checked for binary palindromes. 

 

JohnNichols
Valued Contributor II
358 Views

I used EXCEL to test until EXCEL crashed at 512 in the conversion. 

 

0	0	0	0
0	0	1	1
0	0	3	11
0	0	5	101
0	0	7	111
0	0	9	1001
0	3	3	100001
0	9	9	1100011
3	1	3	100111001

 

 It was fun,   in LISP using CAR and CDR it would be a simple exercise. 

JohnNichols
Valued Contributor II
352 Views

JohnNichols_0-1637985925625.png

The site crashed as I tried to log on to this post set. 

 

JohnNichols
Valued Contributor II
335 Views

of the 200 or so leaders listed on the Euler Problem solving web site, only 1 uses Fortran. 

JohnNichols
Valued Contributor II
279 Views
 else if(n .eq. 21 .and. bin(1:1) .eq. bin(21:21) .and. bin(2:2) .eq. bin(20:20) .and. bin(3:3) .eq. bin(19:19) &
        .and. bin(4:4) .eq. bin(18:18) .and. bin(5:5) .eq. bin(17:17) .and. bin(6:6) .eq. bin(16:16) .and. bin(7:7) .eq. bin(15:15) .and. bin(8:8) .eq. bin(14:14) &
        .and. bin(9:9) .eq. bin(13:13) .and. bin(10:10) .eq. bin(12:12)  ) then

It was interesting to solve this problem. The Euler people ask that you do not post the solution, it was 167 lines of code, sans comments.  

The bin is a character64 that holds the binary number being tested.  n is the trimmed length, is there a way to make this simpler, it is quite brutish. 

write(bin_representation, fmt='(B0)') i

I was thinking a do loop ? 

Reply