1. Re: Project Programmer Wanter - PERMENUM v1.1 anyone?

Fernando Bauer wrote:
> 
> CChris wrote:
> > 
> > The following merges the final file size test with Fernando's code.
> > On my WinXP pro machine, the drive size is not available (function not
> > supported).
> > I incluede a workaround.
> > If you are running under actual DOS, this may work for you. Otherwise, oyou
> > have to execute an .exw file using exwc.exe, and replace my code by Windows
> > API code that fetches available space on drive. Are you stuck with DOS,
> > really?
> > 
> 
> [snipped Eu code]
> 
> Firstly, thanks CChris for your implementation and comments!
> Secondly, I want to note that I made a mistake in the specification of the
> limit
> of the number of variations (permutations). Actually, the limit of index v in
> function VariationRep is 2^53 (maximum contiguous integer in an atom). There
> are many powers that are between 2^52 and 2^53 (ex.: 3^33, 21^12, 27^11,
> 28^11,
> 37^10, ...). However, in the program, because the argument "a-i" in call to
> VariationRep, the actual limit would be (2^53)-1, but with the original test
> "if a+1=a" the final limit is (2^53)-2. Actually, these limits will not be
> reached
> because the current storage capacity, so they aren't used in CChris' code.
> 
> Following is a version based on CChris' code:
> 
> - I guess that a version of Ret's items a to e is implemented.
> - A small optimization was made in saving the variations to the file.
> - I didn't understand CChris' expression "log(length(s))*(n+1)", so I
> substituted

The final file size, if all goes well, is number_of_records*size_of_records.,
possibly *2 in mode b. In order to avoid overflow in poer(), I compute log(size)
rather than size. The number of records is power(n,length(s)), whose log is
log(length(s))*n. The record size is length(s), logarithms add up when
miltiplying the numbers and
log(length(s)) factors out.

> it for another one.
> - I don't know if CTR-C test (check_break()) works appropriately in DOS. It
> seems that in WinXP it doesn't (I can't stop after the beginning of the
> generating
> process).
> 
> }}}
<eucode>
> include get.e
> include wildcard.e
> include graphics.e
> include misc.e
> include machine.e
> include file.e
> 
> atom mb_drive_space,buffer_lo -- # Mo available on drive, DOS buffer
> atom file_size_log
> 
> constant one_meg=1048576
> 
> procedure terminate(integer i)
>    puts(1,"\nPlease press any key to terminate the program.\n")
>    if wait_key() then end if
>    abort(i)
> end procedure
> 
> function VariationRep(atom v, integer n, sequence s)
> integer ls
> sequence p
> 
>    if v < 1 then return {} end if
>    v -= 1
>    p = repeat(0,n)
>    ls = length(s)
>    for i = n to 1 by -1 do
>       p[i] = s[remainder(v,ls)+1]
>       v = floor(v/ls)
>    end for
>    return p
> end function
> 
> integer n,fn
> atom a,t
> sequence s,mode,fname,pos
> 
> function OpenFile(sequence fname, sequence mode)
> sequence in
> integer fn
> 
>    if mode[1]='w' then
>       fn = open(fname,"r")
>       if fn >= 0 then
>          puts(1,"That file already exists.\n")
>          while 1 do
>             in = lower(prompt_string("Overwrite and replace the file [y/n]:"))
>             if check_break() then terminate(1) end if
>             if equal(in,"n") then return -1 end if
>             if equal(in,"y") then exit end if
>             puts(1,"Please enter either y or n.\n")
>          end while
>          puts(1,'\n')
>          close(fn)
>       end if
>    end if
>    fn = open(fname,mode)
>    if fn < 0 then
>       printf(1,"Could not open output file: %s\n",{fname})
>       puts(1,"Maybe that data storage device does not exist or your entry was
>       not written in a proper file name format.\n")
>    end if
> return fn
> end function
> 
> function find_drive_space()
>     -- get drive for output file
>     sequence regs
>     atom buffer_hi,truename_ptr,bytes_per_cluster,num_clusters,result
>     integer seg16,off16_lo,off16_hi,second_char,num_bksp
> 
>     regs=repeat(0,10)
>     buffer_lo=allocate_low(256)
>     buffer_hi=buffer_lo+128
>     seg16=floor((buffer_lo+256)/#FFFF) -- avoid segment wrap inside buffer
>     off16_lo=buffer_lo-65536*seg16
>     off16_hi=off16_lo+128
>     poke(buffer_lo,fname)
>     poke(buffer_lo+length(fname),0)
>     regs[REG_DS]=seg16  -- src buffer address
>     regs[REG_SI]=off16_lo
>     regs[REG_ES]=seg16  -- dst buffer address
>     regs[REG_DI]=off16_hi
>     regs[REG_AX]=#6000  -- request true name
>     regs=dos_interrupt(#21,regs)
>     if and_bits(regs[REG_FLAGS],1) then
>         return -1
>     end if
>     -- extract drive name
>     second_char=peek(buffer_hi+1)
>     if second_char=':' then -- local drive
>         poke(buffer_hi+3,0)
>     elsif second_char!='\\' then -- unlikely
>         return 0
>     else -- UNC for network drive
>          -- some versions need extra support
>         truename_ptr=buffer_hi+3
>         num_bksp=0
>         while 1 do
>             second_char=peek(truename_ptr)
>             if second_char=0 then
>                 exit -- unlikely
>             elsif second_char='\\' then
>                 if num_bksp then -- end of second component reached
>                     poke(truename_ptr+1,0)
>                     exit
>                 else -- end of machine name reached, now scan the drive name
>                     num_bksp=1
>                 end if
>             end if
>         end while
>     end if
>     -- get cluster size for drive
>     regs[REG_CX]=44 -- <128 so we can reuse original fname buffer
>     regs[REG_DX]=off16_hi
>     regs[REG_DI]=off16_lo
>     regs[REG_AX]=#7303
>     regs=dos_interrupt(#21,regs)
>     if and_bits(regs[REG_FLAGS],1) or not and_bits(regs[REG_AX],#FF) then
>         return 0 -- error, or unsupported call
>     end if
>     bytes_per_cluster=peek4u(buffer_lo+4)*peek4u(buffer_lo+8) 
>     result=floor(bytes_per_cluster/one_meg)
>     bytes_per_cluster=remainder(bytes_per_cluster,one_meg)
>     -- get available cluster count for drive
> -- In rare cases, this may not be reliable, but reliable 
> -- answers are only guaranteed for local drives using the alternate mechanism.
>     num_clusters=peek4u(buffer_lo+12)
>     mb_drive_space *= num_clusters
>     num_clusters *= bytes_per_cluster
>     return result+floor(num_clusters/one_meg)
> end function
> 
> fn = 1
> allow_break(0)
> puts(1,"PERMENUM - Permutation Enumeration Generator v1.0\n\n")
> puts(1,"Generating \"forward\" or \"forward and reverse paired\", right
> ordered enumeration\n" &
>        "of every permutation of any number of positions and any length of
>        items.\n\n" &
>        "Program may be halted at any given moment by pressing the CTR-C and
>        then ENTER key.\n")
> 
> while 1 do
>    mode = lower(prompt_string("\nEnter whether to generate either a)
>    \"forward\" or b) \"forward and reverse pairs\"\n" &
>                               "of right ordered enumeration of every
>                               permutation [e.g.: a]:\n"))
>    if check_break() then terminate(1) end if
>    if not equal(mode,"a") and not equal(mode,"b") then
>       while 1 do
>       mode = lower(prompt_string("Please enter either a or b:\n"))
>       if check_break() then terminate(1) end if
>       if equal(mode,"a") or equal(mode,"b") then exit end if
>       end while
>    end if
>    n = prompt_number("\nEnter the number of character places for the
>    permutation [e.g.: 4]:\n",{})
>    if check_break() then terminate(1) end if 
>    s = prompt_string("\nEnter the character items to be permutated in the
>    desired forward order for\n" &
>                      "the enumeration [e.g.: xyz]:\n")
>    if check_break() then terminate(1) end if
>    while 1 do
>       fname = prompt_string("\nEnter the file name for the enumeration output
>       to be saved as [e.g.: 4toxyz.txt\n" &
> 
>                             "or c:\\4toxyz.txt]:\n")
>       if check_break() then terminate(1) end if
>       fn = OpenFile(fname,"w")
>       if fn != -1 then exit end if
>    end while
>    
>    -- start size testing
>    mb_drive_space=find_drive_space()
>    free_low(buffer_lo)
>    
>    -- a = power(length(s),n) + 1
>    -- if a+1 = a then
>    --    puts(1,"Too many permutations to process. The limit for the total
>    number of forward and reverse paired," &
>    --           "right ordered permutations to be enumerated is 2^52 [n=2,
>    s=52].\n")
>    --    abort(1)
>    -- end if
>    
>    if mb_drive_space=0 then
>        mb_drive_space=prompt_number("\nDo you know how megabytes of free space
>        you have on that drive? If so, please enter that number, else 0.\n",{})
>        if mb_drive_space=0 then
>            if compare(prompt_string("\nCould no determine available
> space on drive.\nDo you wish to proceed, AT THE RISK OF OVERRUNNING YOUR
> DRIVE? (NOT RECOMMENDED)\nIf so, type YES, any other answer exits program.\n")
>                        ,"YES") then
>                puts(1,"\nProgram halted by user.\n")
>                terminate(1)
>            end if
>        end if
>    end if
>    -- changed check using logarithms, so as to avoid overflows in power()
>    
>    -- file_size_log=log(length(s))*(n+1)
>    -- if equal(mode,"b") then
>    --     file_size_log+=log(2)
>    -- end if
>    
>    if equal(mode,"a") then
<snip>

new topic     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu