I have been asked to translate the following code which finds a maximum non-overlapping increasing sub sequence given a large amount of input. I haven't had much time to learn a lot on Haskell and I am stuck how to actually do it.
Here is the code in Java:
import java.util.*;
public class mnois {
public static int[][] memo;
public static int[][] lis;
public static int[] nums;
public static int[][][] lmemo;
public static int n;
public static String input;
public static String[] arrIn;
public static void main(String[] args) {
Scanner br = new Scanner(System.in);
int t = br.nextInt();
for(int c = 1;c<=t;c++) {
n = br.nextInt();
input = br.nextLine();
arrIn = input.split(" ");
nums = new int[n];
for(int i = 0;i<n;i++){
nums[i] = Integer.parseInt(arrIn[i]);
}
memo = new int[n][n+1];
for(int i = 0;i<n;i++){
Arrays.fill(memo[i], -1);
}
lmemo = new int[n][n+1][n+1];
for(int i = 0;i<n;i++){
for(int j = 0;j<n+1;j++){
Arrays.fill(lmemo[i][j], -1);
}
}
lis = new int[n][n];
for(int i = 0;i<n;i++){
for(int j = i;j<n;j++){
lis[i][j] = lis(i, n, j);
}
}
for(int i = 1;i<=n;i++){
System.out.print(go(0, i));
if (i != n){
System.out.print(" ");
}
}
System.out.println();
}
}
public static int lis(int pos, int last, int max) {
if (pos > max) {
return 0;
}
if (lmemo[pos][last][max] != -1){
return lmemo[pos][last][max];
}
int best = lis(pos+1, last, max);
if (last == n || nums[pos] > nums[last]) {
best = Math.max(best, lis(pos+1, pos, max)+1);
}
return lmemo[pos][last][max] = best;
}
public static int go(int pos , int k){
if (pos >= n) {
return 0;
}
if (memo[pos][k] != -1){
return memo[pos][k];
}
int best = go(pos+1, k);
for(int i = pos;i<n;i++){
if (lis[pos][i] >= k) {
best = Math.max(best, go(i+1, k)+lis[pos][i]);
}
}
return memo[pos][k] = best;
}
}
I am particularly having problems with creating mutable 2D and 3D arrays. Appreciate any help I can get.
This is what I have so far:
import Data.Array.IO
case :: Int -> Int -> Bool
case index n =
if (index >= n)
return True
else do
numElems :: Int <- readLn
strElems <- readLn
nums <- newArray_ (0, numElems) :: Int
addElems nums 0 0 numElems strElems
memo <- newArray ((0, 0), (strElems, strElems+1)) -1 :: IO (IOArray (Int, Int) Int)
lmemo <- newArray (((0,0),(0,0)), ()) -1 :: IO (IOArray (Int, Int) IO (IOArray (Int, Int) Int))
lis <- newArray ((0, 0), (strElems, strElems)) -1 :: IO (IOArray (Int, Int) Int)
addElems :: (IOArray s Int Int) -> Int -> Int -> Int -> String -> IO s ()
addElems arr startArr strIndex finish string =
if (start >= finish) then
return ()
else do
num <- digitToInt $ string !! strIndex
writeArray arr startArr char
addElems arr (startArr+1) (strIndex+2) finish string
lisLoop :: (IOArray s Int Int) -> Int -> Int -> IO s ()
listLoop arr start finish =
if (start >= finish) then
return ()
else do
next 0 finish
where
next i currIdx len =
if (i < len)
writeArray arr (currIdx, i)
next (i+1) currIdx len
Related
I have just tried rewriting some code, originally a short Javascript function, in Haskell. The original has 2 nested loops and the inner loop contains a check for equality against both loop counters:
function f(x, points){
var i, j;
var n = points.length;
var result = 0;
for(i=0; i<n; i++){
var xprod = 1;
for(j=0; j<n; j++){
if(j != i){
xprod *= (x - points[j][0]);
}
}
result += points[i][1] * xprod;
}
return result;
}
I was hoping to be able to simplify it in Haskell, but I couldn't figure out how get hold of the i and j values without effectively writing out every step of the original recursively. In Javascript Array.map passes the list position into the callback function as the second parameter, but it seems that map in Haskell doesn't do this. My current Haskell version looks awful to me as I'm passing in 2 copies of the array (one for each loop):
xproduct :: Int -> Int -> Double -> [(Double,Double)] -> Double
xproduct _ _ _ [] = 1
xproduct i j x (pt:todo)
| i == j = (xproduct i (j+1) x todo)
| otherwise = (xproduct i (j+1) x todo) * (x - (fst pt))
solvestep :: Int -> Double -> [(Double,Double)] -> [(Double,Double)] -> Double
solvestep _ _ _ [] = 0
solvestep i x pts (pt:todo) = ((snd pt) * xprod) + (solvestep (i+1) x pts todo)
where xprod = xproduct i 0 x pts
solve :: Double -> [(Double,Double)] -> Double
solve x points = solvestep 0 x points points
Is there a better way to do this?
I generally avoid using any indices at all, if possible. In this case, what you're really working with is: any one element of the list with all the other elements. No need to express that with index comparison, instead write a function that will give you a suitable look into the list:
pickouts :: [a] -> [(a,[a])]
pickouts [] = []
pickouts (x:xs) = (x,xs) : (second (x:) <$> pickouts xs)
Then, the actual computation becomes just
f :: Double -> [(Double,Double)] -> Double
f x points = sum [q * product [x-p | (p,_)<-ps] | ((_,q),ps) <- pickouts points]
I have an algebraic data type like:
data Toll = Vok Int Bool | Bok Int | Cokd String Char
and another function
getVal :: Int -> Toll
getVal 1 = Cokd "hello" 'c'
getVal _ = Bok 12
I want to call getVal in some function and extract the arguments of Cokd (if the answer was of type Cokd) (maybe using pattern matching).
can I do like:
hello :: Int -> Bool
hello x = if st == "hell" then True else False
where (Cokd st ch) = getVal x
I cannot use monads.
How to do that?
You can use case to pattern-match the result of getVal:
data Toll = Vok Int Bool | Bok Int | Cokd String Char
getVal :: Int -> Toll
getVal 1 = Cokd "hello" 'c'
getVal _ = Bok 12
hello :: Int -> Bool
hello x =
case getVal x of
Cokd st ch ->
st == "hell"
_ -> False
Or create a separate function and pattern match the argument:
hello :: Int -> Bool
hello =
helloToll . getVal
where
helloToll (Cokd st ch) = st == "hell"
helloToll _ = False
The example, that you've provided in the question compiles (with few modifications), but it will throw a runtime exception when you try to call hello with 2 (or any other value different from 1, in which case getValue returns Bok 12, thus (Cokd st ch) = getVal x fails to pattern-match).
Your code seems totally fine, just one correction: the pattern if <expr> then True else False can be replaced with <expr>.
hello :: Int -> Bool
hello x = st == "hell" where (Cokd st ch) = getVal x
However, this code will fail for values other than 1 due to non-exhaustive pattern matching. You need to cover all cases:
hello :: Int -> Bool
hello x = case getVal x of
Cokd st ch -> st == "hell"
_ -> False
I tried check50, and I got some message for the command down below.
#include<cs50.h>
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int main(int argc, string argv[])
{
string a = argv[1];
int s = strlen(a);
if(s == 0)
{
printf("No keyword entered\n");
return 1;
}
for(int k = 0; k < s; k++)
{
if(!isalpha(a[k]))
{
printf("keyword not alphabetical\n");
return 1;
}
}
string t = GetString();
int i = 0;
int x = 0;
int v = 65;
for(int n = strlen(t); i < n; i ++)
{
if(isalpha(t[i]))
{
if(isupper(t[i]))
{
if(isupper(t[i]))
{
if(islower(a[x]))
{
v = v + 32;
}
int p = a[x];
p = p -v;
int 1 =t[i];
1 = 1 - 65;
int b = (1+ p[s%x]%26;
b = b + 65;
char c = b;
printf("%c", c);
x = x+1;
}
if(islower(t[i]))
{
int p = a[x];
p = p - v;
int 1 = t[i];
1 = 1-97;
int b =(1 +p[s%x]%26;
b = b + 97;
char c = b;
printf("%c", c);
x = x + 1;
}
}
else
{
printf)"%c", t[i]);
}
}
printf('\n');
}
Error message:
:| encrypts "a" as "a" using "a" as keyword
:| encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword
:| encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
:| encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
:| handles lack of argv[1]
:| handles argc > 2
:| rejects "Hax0r2" as keyword
How to fix it all?
Question: The simple rule for translating into “Pig Latin” is to take a word that begins with a vowel and add "yay", while taking any word that be- gins with one or more consonants and transferring them to the back before appending "ay". For example, "able" becomes "ableyay" and "stripe" becomes "ipestray". Write a function that converts a string of letters into its Pig-Latin translation.
Implementation:
-- define function to detect vowel
isVowel :: Char -> Bool
isVowel c = elem c ['u','e','o','a','i']
-- define function Latin Pig
lp ::String -> String
lp str = if (isVowel (head str)) then do {str ++ "yay"}
else
do {
str ++ (head str)
tail str
lp str
}
Problem: So far I do not see any problem with my code (logic). Honestly this is my homework for an Intro to Haskell course. However the compiler gives me errors:
**Couldn't match expected type `t0 -> t1 -> t2 -> t3 -> [Char]'
with actual type `Char'
Expected type: [t0 -> t1 -> t2 -> t3 -> [Char]]
Actual type: String
In the first argument of `head', namely `str'
In the second argument of `(++)', namely
`(head str) tail str lp str'
Failed, modules loaded: none.**
What is wrong with my code?!
To begin, think about pattern matching.
Any not empty list can be define as x:xs, with,
x as head list
xs as tail list
then your code become,
-- define function Latin Pig
lp :: String -> String
lp [] = ""
lp (x:xs) = if (isVowel x) then str ++ "yay"
else ..... -- fill here
where str = (x:xs)
don't forget that the operator : is the constructor of list, for example,
'a':"bab" => "abab"
Keep in mind that a string is a list of char.
Furthermore, you can skip the where clause in the previous example, like this,
-- define function Latin Pig
lp :: String -> String
lp [] = ""
lp str#(x:xs) = if (isVowel x) then str ++ "yay"
else ..... -- fill here
Should be enough to help you.
Good luck
Here is another way of putting the pig latin rule:
if a word doesn't begin with a run of consonants, then the translation is the original word followed by "yay"
otherwise the translation is the rest of the word, followed by the initial run of consonants, followed by "ay"
This is easier to translate into Haskell.
(Actual Haskell code elided, as this is homework.)
You will find it helpful to combine your isVowel function with the break function from Data.List.
I'm not sure if it is part of your requirements to use recursion but here is my take on your task. You do not need to use the do monad to achieve what you want (unless that is an objective of the assignment?).
You might want to consider using pattern matching and guards instead of an if else block.
Also, like zurgl said, you can take advantage of matching the string like this: string#(x:xs) which will allow you to do work on the entire string while also using the head x and tail xs.
Note: All strings are lists.
Here is a quick example of what I suggested.
-- define function to detect vowel
isNotVowel :: Char -> Bool
isNotVowel c = notElem c ['u','e','o','a','i']
-- define function Latin Pig
lp :: String -> String
lp [] = []
lp p#(x:xs)
| not $ isNotVowel x = p++"yay"
| otherwise = let (constants, rest) = span isNotVowel p
in (rest++constants++"ay")
Have fun learning haskell!
Some nice resources for learning haskell:
Learn You A Haskell For Great Good
Real World Haskell
Kindly refer following code.
private static BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
System.out.print("Enter sentence: ");
String sentence = getString();
String latin = pigLatinForSentence(sentence);
System.out.println(latin);
}
private static String pigLatinForSentence(String s) {
String latin = "";
int i = 0;
while (i < s.length()) {
while (i < s.length() && !isLetter(s.charAt(i))) {
latin = latin + s.charAt(i);
i++;
}
if (i >= s.length())
break;
int begin = i;
while (i < s.length() && isLetter(s.charAt(i))) {
i++;
}
int end = i;
latin = latin + pigWord(s.substring(begin, end));
}
return latin;
}
private static boolean isLetter(char c) {
return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
}
private static String pigWord(String word) {
int split = firstVowelInSentence(word);
return word.substring(split) + "-" + word.substring(0, split) + "ay";
}
private static int firstVowelInSentence(String word) {
word = word.toLowerCase();
for (int i = 0; i < word.length(); i++)
if (word.charAt(i) == 'a' || word.charAt(i) == 'e' || word.charAt(i) == 'i' || word.charAt(i) == 'o'
|| word.charAt(i) == 'u')
return i;
return 0;
}
private static String getString() throws IOException {
return buf.readLine();
}
Hope this solution help you learn more detail about pig latin.
Is there a way to use functions in Discriminated Unions? I am looking to do something like this:
Type Test<'a> = Test of 'a-> bool
I know this is possible in Haskell using newtype and I was wondering what the equivalent in F# would be.
Thanks.
type Test<'A> = Test of ('A -> bool)
As an expansion on desco's answer you can apply the function tucked into Test with pattern matching:
type Test<'a> = Test of ('a -> bool)
// let applyTest T x = match T with Test(f) -> f x
// better: (as per kvb's comment) pattern match the function argument
let applyTest (Test f) x = f x
Example:
// A Test<string>
let upperCaseTest = Test (fun (s:string) -> s.ToUpper() = s)
// A Test<int>
let primeTest =
Test (fun n ->
let upper = int (sqrt (float n))
n > 1 && (n = 2 || [2..upper] |> List.forall (fun d -> n%d <> 0))
)
In FSI:
> applyTest upperCaseTest "PIGSMIGHTFLY";;
val it : bool = true
> applyTest upperCaseTest "PIGSMIgHTFLY";;
val it : bool = false
> [1..30] |> List.filter (applyTest primeTest);;
val it : int list = [2; 3; 5; 7; 11; 13; 17; 19; 23; 29]