Advertisement
Guest User

Crossword

a guest
Sep 6th, 2015
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. program crossword
  2. implicit none
  3. character*1, allocatable:: grid(:,:)
  4. character*(20) :: words(9)
  5. integer i
  6. , nwords, score,n,casenum, counter, minscore, shuffle_try
  7. allocate(grid(20,20))
  8. cnum: do casenum=1,4
  9.   call readwords
  10.   shuffletry: do shuffle_try=1, 5000
  11.   call shuffle
  12.  ! print*,words(1:nwords)
  13.   grid = ' '
  14.   score=0
  15.   i =1
  16.   counter =0
  17.   wordloop:do
  18.     call addword(grid, words(i),i, n)
  19.     if  (i ==1.or.n > 0)then
  20.       score = score + n
  21.       i =  1+ i
  22.     else if (i<nwords-1) then
  23.       words(i:nwords) = [ words(i+1: nwords), words(i)]
  24.      ! print*, words(i:nwords)
  25.    end if
  26.       counter = counter +1
  27.   !  end if
  28.     if (i> nwords.or. counter > 10) exit wordloop
  29.   end do wordloop
  30.   if (score >= minscore) exit shuffletry
  31.  end do shuffletry
  32.  call printgrid(grid,6)
  33.  call printgrid(grid,11)
  34.  write ( 6, *)score
  35.  write (11,*) score
  36. end do cnum
  37.  
  38.   contains
  39.  
  40. subroutine shuffle
  41. character*(:), allocatable :: temp
  42. integer n,i,m
  43. real h
  44. allocate(temp, mold=words(1))
  45. m=nwords
  46. do i=1,m-1
  47.   call random_number(h)
  48.   n=floor((m-i+1)*h)+i
  49.   temp=words(n)
  50.   words(n) =words(i)
  51.   words(i) = temp
  52. end do
  53. end subroutine
  54.      
  55.  
  56. subroutine readwords
  57.   read (10,*) nwords, minscore
  58.   read(10,*) words (1: nwords)
  59.   print*, words(1:nwords)
  60. end subroutine
  61.  
  62. subroutine addword( grid, word,wn, iscore)
  63.   character*1, intent ( inout):: grid(:,:)
  64.   character*(*), intent ( in):: word
  65.   real score
  66.   integer x,y, xdir, ydir, wordlen, best(4), &
  67.        ysize, xsize, yend, xend, iscore
  68. ,n,wn
  69.   real  maxscore
  70.   logical fits
  71.   xsize =size (grid,1)
  72.   ysize =size(grid,2)
  73.   wordlen=index(word,' ')-1
  74.   best = 0
  75.   maxscore = 0
  76.   do concurrent (x=1:xsize, y=1:ysize, xdir=1:-1:-1, ydir=1:-1:-1 ,&
  77.        xdir*ydir==0 .AND. xdir+ydir/=0 )
  78.     xend= x+(wordlen-1)*xdir
  79.     if (xend<1.or.xend>xsize) cycle
  80.     yend= y+(wordlen-1)*ydir
  81.     if (yend<1.or.yend>ysize) cycle
  82.     if (wn==1) then
  83.       score=ctrscore(xsize,ysize,x,y,xend,yend)
  84.     else
  85.       call random_number(score)
  86.     end if
  87.     iscore = comboscore(grid,word(1:wordlen),x,y,&
  88.          xdir,ydir)
  89.     if(iscore<0)cycle
  90.     if (score+iscore>maxscore) then
  91.       maxscore=score + iscore
  92.       best=[x,y,xdir,ydir]
  93.     end if
  94.   end do
  95.   x=best(1)
  96.   y=best(2)
  97.   xdir=best(3)
  98.   ydir=best(4)
  99.   iscore = int(maxscore)
  100.   if (iscore<1.and.wn.ne.1) return
  101.   do n=1,wordlen
  102.     grid(x+xdir*(n-1), y+ydir*(n-1)) =word(n:n)
  103.   end do
  104. end subroutine addword
  105.  
  106. subroutine printgrid(grid,lunit)
  107. character*(1), allocatable :: grid(:,:)  
  108. character *(1):: ch
  109. integer i,j,lunit
  110. do i=1, size(grid, 1)
  111.   do j=1, size(grid, 2)
  112.     ch = grid(i,j)
  113.     if (ch == '  ') ch= '.'
  114.     write(lunit,'(a)',advance='NO')ch
  115.   end do
  116.   write (lunit, *)  ' '
  117. end do
  118. end subroutine
  119.  
  120. pure function ctrscore(xsize, ysize,xstart,ystart,xend, yend)result(score)
  121.     ! position score... penalize for manhattan distance from center of grid
  122.     integer, intent(in) :: xsize, ysize, xstart, ystart, xend, yend
  123.     integer i,x,y
  124.     real xctr, yctr, dist, score
  125.     xctr = (xstart + xend)/2.
  126.     yctr = (ystart + yend)/2.
  127.     score =1. - abs( xsize / 2. - xctr)/xsize -&
  128.          abs( ysize/2. - yctr)/ysize
  129. end function ctrscore
  130.  
  131. pure function comboscore(grid,word,xstart,ystart,xdir,ydir) &
  132.        result(iscore)
  133.     ! return value is numer of overlapping positions.  if the word
  134.     ! does not fit in the given position, return -1
  135.     character*1, intent(in) :: grid(:,:)
  136.     character*(*),intent(in) ::word
  137.     integer iscore
  138.     integer, intent(in):: xstart,ystart,xdir,ydir
  139.     integer x,y,n, wl
  140.  
  141.        iscore =0
  142.  
  143.     wl=len(word)
  144.     do n=1, wl
  145.        x=xstart+(n-1)*xdir
  146.        y=ystart+(n-1)*ydir
  147.        if (grid(x,y) == ' ') cycle
  148.        if (grid(x,y) /= word(n:n)) then
  149.             iscore =-1
  150.             return
  151.        else
  152.           iscore =iscore +1
  153.        end if
  154.     end do
  155. end function comboscore
  156.  
  157.  
  158. end program crossword
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement