I started writing this in OCaml in order to get a count of each character in a file.
open Hashtbl;;
type 'a option = None | Some of 'a;;
let rec charCount fd ht =
let x =
try Some (input_char fd)
with End_of_file -> None
in
match x with
| Some c ->
let val =
try find (ht c)
with Not_found -> 0
in
replace ht c (val+1);
charCount fd ht
| None -> ();;
let ht = create 0;;
let loadHisto fn =
let fd = open_in fn
in
charCount fd ht;;
loadHisto "testfile";;
iter printf("%s => %s\n") ht;;
When I try to compile it with ocamlc -c I get the message :
Error: Syntax error:
val is a reserved word, you can't use it
Related
data T = A String | B String
p : ((A s) = (A s')) -> (s = s')
If I have (A s) = (A s'), how do I obtain s = s'?
P.S. I'm new to Idris. Feel free to edit my question for code style or to add pertinent keywords.
Pattern match on Refl:
data T = A String | B String
p : ((A s) = (A s')) -> (s = s')
p Refl = Refl
I'm very new to Idris (and dependent types). I was trying to do write a program to check if a string is a palindrome of not. To do that, I decided to compute the length of the string, and compute
q,r = (strlen `div` 2, strlen `mod` 2)
and then split the string as follows:
lhalf,rhalf = (substr 0 (q+r) str, substr (q-r) (q+r) str)
This takes care of both odd and even length strings. The problem is that Idris needs a proof that r < q since both q and r are Nat.
My question is: How do I express the fact that r
Here's the full sample of my code:
module Main
isPalindrome : (str : String) -> String
isPalindrome str =
let split = half_half str
in show ((fst split) == reverse (snd split))
where
strlen : Nat
strlen = length str
divMod : Nat -> Nat -> (Nat,Nat)
divMod x y = (x `div` y, x `mod` y)
half_half : String -> (String, String)
half_half "" = ("","")
half_half x = let
(q,r) = divMod strlen 2
in
(substr 0 (q+r) x,
substr (q-r) (q+r) x)
main : IO ()
main = repl "> " isPalindrome
You can't proof that r ≤ q because it's not true. For example, given the string "a" you have strlen = 1 and therefore q = 0 and r = 1. In this example r ≤ q is clearly false.
Note that you can implement isPalindrome simply by
isPalindrome: String -> Bool
isPalindrome str = str == reverse str
In my exercise I have to write OCaml module given its signiture:
module type Range
= sig
type t
val range : int * int -> t
(*val list_of_range : t -> int list*)
end
The module I have so far:
module Range =
struct
type t = int
let range (n,m) =
if m > n then () else (n,m)
end
The task for range (n,m) is to take 2 integers and if n <= m then give out a tuple (n,m). Otherwise (). If I try to run this code, I get error The expression has 'a * 'b but an expression was expected of type unit. Can anyone help me to move forward with this?
PS. It's my first day with OCaml.
PPS. I have commented out the list of range.. part because this is the second part of the exercise and wouldn't work anyway if the first part isn't working.
UPDATE
I have updated my code and results seem promising.
module type Range
= sig
type t
val range : int * int -> t
val list_of_range : t -> int list
end
module Range =
struct
type t = int
let range (m,n) =
if m > n then (0,0) else (m,n)
let rec list_of_range (m,n) =
let t = range(m,n) in
let x = fst(t) in let y = snd(t) in
if x = 0 && y = 0 then [0] else x :: list_of_range(x+1,y)
end
The code above gives me almost perfect expected result. If I give input (1,5), the result is [1;2;3;4;5;0]. The problem is the 0 as the last element in the list. Why is is there? Where does it come from?
the issue comes from your function range, it cannot return a unit type (i.e. () ) and a tuple. In addition, it violates the signature, where you define range as a function that returns an int.
I have a sequence of numbers as follows:
1 , 1, 5, 13, 41, 121, 365, ....
The first two values are:
N(1) = 1 and N(2) = 1
As from 3rd value, N(i) = 2*N(i-1) + 3*N(i-2)
The issue I am facing with is: If I give an argument of p, it should return me the last values of the sequence < p (Using fortran77).
For instance, if p = 90, it should return the value 41.
a = 1
b = 1
while b < p:
c = 2 * b + 3 * a
a = b
b = c
return a
The Fortran equivalent is:
function fct(p) result(a)
integer, intent(in) :: p
integer :: a, b, c
a = 1
b = 1
do while (b < p)
c = 2 * b + 3 * a
a = b
b = c
enddo
end function
program test
integer :: fct
external fct
print *,fct(90)
end program
Assuming you already have the sequence in a variable lst, and p set,
max(filter(lambda x:x<=p, lst))
def get_last_element(p):
n1 = 1
n2 = 1
while True:
if n2 > p:
return n1
n1, n2 = n2, 2*n2 + 3 * n1
print(get_last_element(90))
I wrote a piece of code in Fortran 2003. I defined a type which has memory for two last parts of the sequence.The procedure is a recursive function. The type can be used standalone to get n-th part of the sequence or efficiently placed in a loop to find parts in a row (not necessarily beginning at 1) as it has memory of previous parts. (compiler: gfortran 4.8).
The type is defined in mymod.f90 file as
module mymod
implicit none
type seq_t
integer :: saved_i = 0, saved_val_i = 0, saved_val_i_1 = 0
contains
procedure :: getpart => getpart_seq
end type
contains
recursive function getpart_seq(this,i) result(r)
class(seq_t) :: this
integer, intent(in) :: i
integer :: r,r_1,r_2
if (i.eq.1.or.i.eq.2) then
r = 1
elseif(i.eq.this%saved_i) then
r = this%saved_val_i
elseif(i.eq.this%saved_i-1) then
r = this%saved_val_i_1
else
r_1 = this%getpart(i-1)
r_2 = this%getpart(i-2)
r = 2*r_1 + 3*r_2
this%saved_val_i_1 = r_1
end if
this%saved_i = i
this%saved_val_i = r
end function getpart_seq
end module mymod
The main program for the requested case is
program main
use mymod
implicit none
type (seq_t) :: seq
integer :: i,p,tmp_new,tmp_old,ans
! Set the threshold here
p = 90
! loop over parts of the sequence
i = 0
do
i = i + 1
tmp_new = seq%getpart(i)
print*,tmp_new
if (tmp_new>p) then
ans = tmp_old
exit
end if
tmp_old = tmp_new
end do
print*,"The last part of sequence less then",p," is equal to",ans
end program
The outcome is
1
1
5
13
41
121
The last part of sequence less then 90 is equal to 41.
I'm trying to create a small module for doing decimal-based calculations. A number is stored as an integer mantisse, with a precision value specified by an int:
data APNum =
{ getMantisse :: Integer
, getPrecision :: Int }
For instance:
APNum 123 0 -> 123
APNum 123 1 -> 1.23
APNum 123 2 -> 12.3
...
(negative precision is not allowed).
Now I wrote this function, which adjusts the precision automatically by stripping as many trailing zero's as possible:
autoPrecision :: APNum -> APNum
autoPrecision x#(APNum m p) = if p > maxPrecision
then autoPrecision $ setPrecision x maxPrecision
else autoPrecision' m p where
autoPrecision' m p = let (m',r) = m `divMod` 10 in
if r /= 0 || p <= 0 then APNum m p else autoPrecision' m' (pred p)
(MaxPrecision and setPrecision are obvious, I think).
The problem is, this snippet has a very bad performance, specially n numbers with more then 10000 digits. Are there any simple optimizations?
You can use binary search to find the highest power of 10 which divides m, instead of trying all consecutive values.
import Numeric.Search.Range
import Data.Maybe
data APNum = APNum{getMantisse :: Integer, getPrecission :: Int} deriving Show
setPrecision (APNum m _) x = APNum m x
maxPrecission = 200000
findDiv x = pred $ fromJust $ searchFromTo (p x) 0 maxPrecission where
p x n = x `mod` 10^n /= 0
autoPrecision :: APNum -> APNum
autoPrecision x#(APNum m p)
= if p > maxPrecission then
autoPrecision $ setPrecision x maxPrecission else APNum m' p'
where d = min (findDiv m) p
p' = p - d
m' = m `div` 10^d
I'm using the binary-search package here which provides searchFromTo :: Integral a => (a -> Bool) -> a -> a -> Maybe a. This should give you a big speedup.
Looks like even straightforward string operation is still faster:
maxPrecision = 2000000
autoPrecision (APNum m p) =
let p' = min p maxPrecision
(n',ds) = genericDropNWhile (=='0') p' $ reverse $ show m
in APNum (read $ reverse ds) n'
where
genericDropNWhile p n (x:xs) | n > 0 && p x = genericDropNWhile p (n-1) xs
genericDropNWhile _ n xs = (n,xs)
Test with this:
main = print $ autoPrecision $ APNum (10^100000) (100000-3)
EDIT: Oops, faster only for numbers with lots of zeroes. Otherwise this double conversion is definitely slower.
also x mod 10 == 0 implies x mod 2 == 0, and that is cheaper to test for