Perl Weekly Challenge 133: Integer Square Root

by Abigail

Challenge

You are given a positive integer $N.

Write a script to calculate the integer square root of the given number.

Please avoid using built-in function. Find out more about it here.

Examples

Input: $N = 10
Output: 3

Input: $N = 27
Output: 5

Input: $N = 85
Output: 9

Input: $N = 101
Output: 10

Solution

The challenging part of this challenge is:

Please avoid using built-in function.

Perl

Calculating the integer root of a number $n not using built-in functions is easy. The module Math::Prime::Utils provides a function sqrtint which does exactly what is asked. But it doesn't print it. And both say and print are built-in functions.

So, we have to do something else. Our solution is pass the bucket to AWK, and have AWK calculate the integer root. But how to call AWK? Both exec and system are build-in functions, and so is open.

Which leaves us backticks (``). But we can't just use backticks and leave it like that, as the backticks run the given command, and collect its output, which is returned. However, we cannot print that, for the same reasons as explained above.

So, we will have AWK print directly to the terminal. AWK can redirect output the same way as the shell can, using > file after a print statement. /dev/tty is the pseudo-file representing the terminal.

There is one more snag we have to tackle. Since we're reading numbers from standard input, every read number ends with a newline. And AWK treats newlines as statement terminators without any regard to context (basically, if the newline is not escaped, it will terminate the statement). So, we have to get rid of it, but we cannot use chop nor chomp, due to the "no build-in" restriction. But we have s/// available, which we use to remove anything which isn't an ASCII digit.

Which gives us the following program:

`awk 'BEGIN {print (int (sqrt (${\s/[^0-9]+//gr}))) > "/dev/tty"}'` for <>;

Find the full program on GitHub.


Please leave any comments as a GitHub issue.