# Functions or Not?

# Functions or Not?

Rhaseven7h + 5 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 :)

nichijou + 0 comments Thanks! I just thought I missed some math knowledge before reading your comment... what a pity, I thought I could learn something new.

zylviij + 3 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 + 2 comments 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

M_F_H + 0 comments I'm a Haskell newbie and reading input data is the most difficult part of the problem for me. I don't see where your code structures the input data into the "grouping" required in this task.

I mean, how is the function "run" (if I understood at least that part) supposed to get T, and then, for 1..T, the value of N and the list of (x,y) as required for this problem? (I understand that we could simply "skip" the initial T but then (until EOF is reached) definitely need to get the N in order to know how many lines (x,y) we must read -- where am I wrong?)

I'm keen to switch from imperative to functional programming, but as far as the "I/O" is concerned, the problem statement "there are T test cases and for each test case..." already contains the declarative "for". And I'd like to write a function that receives a vector of N pairs (x,y), but how to get there without doing "for i in 1..N: read [x, y] and append to the list L" ?

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

ISlicedI + 0 comments Crap, I spent quite some time working out how to get it to output anything..

vestail + 2 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") } } }

kaganasg + 0 comments Thanks for adding the io code, very helpful.

Your answer is hilarious. Nice hack. And you understand it wouldn't work if you get a duplicate relation, right? Like if the test set includes (1,2),(1,2). Your function would print NO, while this describes a valid funcition. But kudos for the insight!

patrick_ce + 0 comments I used the properties of Maps.

object Solution { def functionTest() : Unit = { val X = scala.io.StdIn.readInt() val data = Iterator.continually(readLine()) .take(X) .collect(_.split(" ") match { case Array(s1, s2) => (s1.toDouble, s2.toDouble)}) .toList println(if (data.toMap.size == data.length) "YES" else "NO") } def main(args: Array[String]) { val N = scala.io.StdIn.readInt() for (_ <- 1 to N) { functionTest } } }

Tleilaxi + 3 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.

belokopytov87 + 0 comments you need to trim string before parsing it

`let read_int_value () = read_line () |> String.trim |> int_of_string`

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

Sort 43 Discussions, By:

Please Login in order to post a comment