# Functions or Not?

# Functions or Not?

Rhaseven7h + 4 comments ## Might be helpful to know ...

In case it is useful for someone, in the context of this challenge, a valid function is that which for a given input, ALWAYS gives the same output.

### VALID Function

Given a

`function f()`

that functions as:f(1)=1 f(2)=2 f(3)=3 f(2)=2 f(4)=1000

It is considered

**VALID**, as outputs are always in a 1:1 relation with inputs, even although we don't know the exact way the relationship (function) works (i.e. we got no idea how f(4) gives 1000).

### INVALID Function

A

`function g()`

which functions as follows:g(1)=1 g(2)=333 g(3)=89 g(2)=777 g(4)=1000

The above function g, is

**NOT VALID**, since, for input 2, we get two different results, first 333, then later we get 777.

**NOTE**: It is worth noting that multiple inputs*may*give the same output:f(1)=99 f(2)=99 f(3)=99

Would still be a valid function.

xamadeus + 0 comments Nice explaination. I was confused by this notion too.

harjolgoo + 0 comments This practice's test cases do not concern about f(2)=2 f(3)=2 or f(1)=99 f(2)=99 f(3)=99

phi_ba + 0 comments Thank you, your explanation makes a whole lot more sense than the one which is provided.

jcacooper + 0 comments Good explanation. Another way to think about it that helps me (though if it doesn't help you, probably best just to forget about it) is to consider the result if I graphed the function. So if the x axis is x, and the y axis is f(x), then for a valid function, there should be no place along the x axis where I could draw a vertical line directly down or up and have that line intersect the function's curve/line in more than one place.

Using the examples given above, if you graphed the valid function outputs, you would see that there is only one output for each x input (i.e. only one spot on the graph for each x), and thus I cannot draw a vertical line intercepting the function in more than one place. That is NOT the case however with the invalid input, as I could draw a line and intercept the function's output for 2 at two places.

I hope this helps to clarify things for someone :)

zylviij + 2 comments Here is a template for haskell.

import Control.Monad valid :: [(Int, Int)] -> Bool valid f = -- code goes here -- main = do t <- fmap (read::String->Int) getLine forM [1..t] (\_->do n <- fmap (read::String->Int) getLine func <- forM [1..n] (\_->do fmap ((\[a, b]->(a,b)).map (read::String->Int).words) getLine :: IO (Int, Int)) putStrLn $ if valid func then "YES" else "NO")

knusprigekroete + 1 comment Thank you! Is there some good Haskell IO Tutorial? I struggle with reading from stdin and writing to stdout and spend much more time than necessary reading stackoverflow and hoogle just to write a million of ugly recursive functions to do it.

Fiorix + 1 comment use this as pattern for IO:

main :: IO () main = do n_temp <- getLine let n = read n_temp :: Int forM_ [1..n] $ \boh -> do q_temp <- getLine let q = read q_temp :: Int rawInput <- getMultipleLines q let input = [(read (words str !! 0) :: Int, read (words str !! 1) :: Int ) | str <- rawInput] -- here starts your code getMultipleLines :: Int -> IO [String] getMultipleLines n | n <= 0 = return [] | otherwise = do x <- getLine xs <- getMultipleLines (n-1) let ret = (x:xs) return ret

It works with most input format of HackerRank:

- First read and parse an integer (n_temp and n)
- For n times read another number from input called q and read the next q lines with getMultipleLines. It returns a list of q lines as strings.
- To parse the numbers inside a single line, use list comprehension to iterate on the lines and the function "words" to split the values. This code works if every line contains exactly two integers and put them in a list of type [(Int, Int)]

ProofOfPizza + 1 comment Thx! This is helpful. All this IO stuff was getting pretty ugly :)

wirefox + 1 comment That's still ugly, IMO. Here's my runner:

readInt x = read x :: Int main = putStr . unlines . run . (map readInt) . words =<< getContents

From run, you can just work with pure functions like the Haskell gods intended.

matthias_a + 1 comment how do you know how many lines to read? In a situation where a user is inputting a variable set of inputs, would this work?

If you run this it will just ask for inputs forever.

also, I think that you don't need to define your own read if your run function has a definition

`run :: [Int] -> [String]`

wirefox + 1 comment HackerRank tells you all you need to know about the input, so it's a completely different situation from an arbitrary CLI. This approach works for the type of problems on this particular site, and for the typical use case where input comes from a terminating program or a file.

It actually won't run forever because of a handy thing called EOF.

Nice idea about the type sig, though.

matthias_a + 1 comment how would you write

ms <- forM [1..n] $ const $ getLine let d = M.fromList $ (\[x,y] -> (x,y)) . words <$> ms

on one line?

wirefox + 0 comments d <- M.fromList <$> map ((\[x,y] -> (x,y)) . words) <$> replicateM n getLine

matthias_a + 0 comments Why did you need to convert String to Int? and why did you need to put the numbers in tuples?

Tleilaxi + 2 comments I think there is a problem in the input of the tests case of OCaml. Just doing the simple

let a = read_int ();;

that should normally read the first line of the input (the number of tests cases), fail with the exception

`"int_of_string"`

meaning that the conversion was impossible. There's probably an odd character or byte in the input that' s not displayed when it's printed, because when I copy/paste the inputs of the tests cases as displayed in my browser and run them with "Test against custom input", they execute without errors.

hector_pelletier + 1 comment Same problem here :c

jeremie_salvucci + 0 comments Same issue here. I finally wrote it using my own conversion functions.

vestail + 0 comments My strange scala solution.

object Solution { def main(args: Array[String]) { val n = io.StdIn.readInt() (1 to n).foreach { i => val k = io.StdIn.readInt() val list = (1 to k).map(x => io.StdIn.readLine.split("\\s+")(0)).toList if (list.distinct.size == list.size) println("YES") else println("NO") } } }

GeneralGrievous + 2 comments This input is a bit tricky. My code may help F# folks.

open System let readList n parser = Seq.initInfinite (fun _ -> Console.ReadLine()) |> Seq.take n |> Seq.map parser |> Seq.toList let parseRelation (s: string) = match s.Split(' ') with | [|x|] -> int x, None | [|k; v|] -> int k, Some (int v) | _ -> failwith "OhGodWhy" let readTestCase () = let n = int <| Console.ReadLine() readList n parseRelation let isFunc relations = relations |> Map.ofList |> Map.toSeq |> Seq.length |> (=) (List.length relations) let boolStr = function | true -> "YES" | false -> "NO" [<EntryPoint>] let main args = let t = int <| Console.ReadLine() Seq.initInfinite (fun _ -> readTestCase ()) |> Seq.take t |> Seq.map isFunc |> Seq.map boolStr |> Seq.iter (printfn "%s") 0

Goto10 + 1 comment Dude, this is a complete solution. But agreed, the goal of the task should be to design a function that can say if there's a 1-to-1 relation between input and output values, not struggling with I/O. The most challenging part, at least for me, is reading the input and transforming it to something usable and then mapping the results to "YES" or "NO" strings.

GeneralGrievous + 0 comments Yes. I quitted HackerRank challenges because I usually spend too much time adjusting input and output instead of solving the problem itself.

DechTech + 0 comments I tried to use your parser function and noticed it doesn't take into account the number of test cases (which is why the second int needs to be an option). So I added it and it parses the input as intended and without needing the pesky int option. Here,

let readList n parser = Seq.initInfinite (fun _ -> System.Console.ReadLine()) |> Seq.take n |> Seq.map parser |> Seq.toList let parseRelation (s: string) = match s.Split(' ') with | [|k; v|] -> int k, int v | _ -> failwith "OhGodWhy" let readTestCase () = let n = int <| System.Console.ReadLine() readList n parseRelation let readInput () = let n = int <| System.Console.ReadLine() Seq.initInfinite (fun _ -> readTestCase()) |> Seq.take n |> Seq.toList [<EntryPoint>] let main argv = printfn "%A" <| readInput() System.Console.ReadKey true |> ignore 0

As it is it'll only print the parsed input and wait before exiting, but it shouldn't be an issue to use it as a template to solve the challenge

jt_armstrong + 2 comments Any suggestions for how to do the stdin for this in haskell?

pancro + 0 comments Omitting type definitions and formalities (which are very important in the real world) I'd start from the building blocks and write an action (not a function) that reads a pair of values from a line and returns a tuple, something like this:

readPair :: IO (Int, Int) readPair = do text <- getLine let pairs = (read ((words text)!!0) :: Int, read((words text)!!1) :: Int) return pairs

readPair is clunky and can be written much more elegantly but you get the gist

then I'd write an action that reads a test case, which is made by an integer (the number of pairs) and a list of pairs, something like this:

readTestCase :: IO [(Int, Int)] readTestCase = do text <- getLine let n = read text :: Int replicateM n readPair

Finally I'd write an action that parses the first line (number of testcases) and calls readTestCase appropriately, aggregating all testcases in a list:

readInput :: IO [[(Int, Int)]] readInput = do text <- getLine let n = read text :: Int let cases = replicateM n readTestCase cases

Finally you can use this IO action in your main:

main :: IO () main = do testCases <- readInput -- process your test cases here

Hope you get the idea. This is not the most elegant way and it looks fairly procedural but many IO actions looks procedural by nature.

If this was a real world piece of code, I'd work on defing my own data type (e.g. a

`Mapping`

could be an`(Int, Int)`

tupe, a`PossibleFunction`

could be a list of mappings`[Mapping]`

, etc.)karoyakani + 0 comments ... main = flip replicateM_ sub =<< readLn sub = putStrLn . (\b -> if b then "YES" else "NO") =<< sol <$> (readLn >>= getIntPairs) getIntList :: IO [Int] getIntList = fmap read <$> words <$> getLine getIntPairs :: Int -> IO [(Int, Int)] getIntPairs = flip replicateM getIntPair getIntPair :: IO (Int, Int) getIntPair = (,) <$> head <*> last <$> (fmap read . words <$> getLine) sol :: [(Int, Int)] -> Bool sol ps = ...

ebolinger + 3 comments Can anyone clarify what they mean by "a valid function"? My understanding is that each domain value must map to only 1 value in the range. But the relationship can be arbitrary.

Does the question imply one-to-one functions (where the inverse is also a function)?

Are they looking for relationships that can be represented by algebraic expressions? Why not trig functions?

pktippa + 0 comments As per the given constraints "x and y both are integers" it may not constitue to trig functions

slacker_hacker + 1 comment I was confused by this too. Have a go at submitting any old solution, then look at the cases for test 2 where the result should be 'NO' and it should all become clear.

methusaleh + 0 comments I too examined the test data, but got stumped by #2 in test 2 which flags as a valid function. At the end it changes from being a linear relationship into something quite different. I guess I am missing the intent of the question. e.g.

(97, 403) (98, 402) (99, 401) (100, 499)

ebolinger + 1 comment Hi All. After sleeping on it & debugging my I/O code, I prepended each result to a List, but forgot to call

`.reverse`

before printing! So my output was in the wrong order. For anyone looking for "what is a valid function", this is a good reference: https://en.wikipedia.org/wiki/Function_(mathematics)methusaleh + 0 comments Thanks. Armed with that link I was able to solve the problem. I admit I probably should have googled it first.

agasperi + 0 comments This is my solution. I didn't know about forM and fmap.

esParValido :: [Int] -> [[Int]] -> Bool esParValido _ [] = True esParValido p (x:xs) = if ((p !! 0) == (x !! 0)) && ((p !! 1) /= (x !! 1)) then False else esParValido p xs; lineas :: Bool -> Int -> [[Int]] -> IO () lineas b l p | l == 0 = if b then putStrLn "YES" else putStrLn "NO" | b == False = do linea <- getLine lineas b (l-1) []; | (length p) == 0 = do linea <- getLine let parActual = map (read :: String -> Int) (words linea) lineas b (l-1) (parActual : p) | otherwise = do linea <- getLine let parActual = map (read :: String -> Int) (words linea) if esParValido parActual p then lineas b (l-1) (parActual : p) else lineas False (l-1) (parActual : p); casos :: Int -> IO () casos n | n == 0 = return () | otherwise = do line <- getLine let numberLine :: Int numberLine = read line lineas True numberLine [] casos (n-1); main :: IO () main = do line <- getLine let numberCases :: Int numberCases = read line casos numberCases

AndresReyMaz + 0 comments Common Lisp (SBCL):

(defun lst-equal (l c) (if l (if (eq (car l) c) (lst-equal (cdr l) c) ()) t)) (defun get-all-second (fir l) (if l (if (eq (car (car l)) fir) (cons (cdr (car l)) (get-all-second fir (cdr l))) (get-all-second fir (cdr l))) ())) (defun f (l) (if l (if (lst-equal (get-all-second (car (car l)) l) (cdr (car l))) (f (cdr l)) "NO") "YES")) (defun read-pairs (n) (if (eq n 0) () (cons (list (read *standard-input*) (read *standard-input*)) (read-pairs (- n 1 ))))) (defun solve-case () (f (read-pairs (read)))) (dotimes (i (read)) (format t "~a~%" (solve-case)))

naderghanbari + 0 comments For Scala folks: there are different ways to terminate the recursion/fold early (to return false immediately upon seeing the first vioation).

If you are new to FP try doing it yourslef with recursion.

Another way is using a

`return`

keyword in the`foldLeft`

. Although it's not 100% functional to do that (kind of cheating), it seems to be acceptable.Another way is to use lazy data structures such as

`Stream`

. Look at`.toStream`

on collections (`Seq`

, or`Array`

) and`.scanLeft`

(similar to`foldLeft`

but keeps intermediate results), and finally either`exists`

or`forall`

for early termination.Another way (used in other FP languages such as Erlang) is to use exceptions, but it's not the best idea to do so in JVM.

Sort 29 Discussions, By:

Please Login in order to post a comment