Programming Riddle: Counting down without subtracting [closed]
-
11-09-2019 - |
Question
Ok, goal by example : a command-line app that does this:
Countdown.exe 7
prints 7 6 5 4 3 2 1
No form of subtracting (including use of the minus sign) or string reverse what so ever is allowed.
waaaaay too easy apparently :-) An overview of the answers (the principles at least)
- By adding and recursion
- By using modulo
- By pushing and popping, (maybe the most obvious?)
- By using overflow
- By using trial and error (maybe the least obvious?)
Solution
How about adding and recursion?
public void Print(int i, int max) {
if ( i < max ) {
Print(i+1, max);
}
Console.Write(i);
Console.Write(" ");
}
public void Main(string[] args) {
int max = Int32.Parse(args[0]);
Print(1, max);
}
OTHER TIPS
x = param;
while (x > 0) {
print x;
x = (x + param) mod (param + 1);
}
Here's a method you missed, trial and error:
import java.util.Random;
public class CountDown
{
public static void main(String[] args)
{
Random rand = new Random();
int currentNum = Integer.parseInt(args[0]);
while (currentNum != 0)
{
System.out.print(currentNum + " ");
int nextNum = 0;
while (nextNum + 1 != currentNum) {
nextNum = rand.nextInt(currentNum);
}
currentNum = nextNum;
}
}
}
Push 1-7 onto a stack. Pop stack one by one. Print 7-1. :)
use 2's compliment, after all this is how a computer deals with negative numbers.
int Negate(int i)
{
i = ~i; // invert bits
return i + 1; // and add 1
}
void Print(int max)
{
for( int i = max; i != 0; i += Negate(1) )
{
printf("%d ", i);
}
}
Prepend the numbers into a string buffer.
String out = "";
for (int i = 0; i < parm; i++)
{
out = " " + (i+1) + out;
}
System.out.println(out);
c/c++, a bit of arithmetic overflow:
void Print(int max)
{
for( int i = max; i > 0; i += 0xFFFFFFFF )
{
printf("%d ", i);
}
}
I note that nobody posted the stupidest possible answer, so I'll go ahead and share it:
int main (int argc, char **argv) {
if ( ( argc < 1 ) || ( atoi(argv[1]) != 7 ) ) {
printf("Not supported.\n");
} else {
printf("7 6 5 4 3 2 1\n");
}
}
Don't hate me: See? I admitted it's stupid. :)
use a rounding error:
void Decrement(int& i)
{
double d = i * i;
d = d / (((double)i)+0.000001); // d ends up being just smaller than i
i = (int)d; // conversion back to an int rounds down.
}
void Print(int max)
{
for( int i = max; i > 0; Decrement(i) )
{
printf("%d ", i);
}
}
Bitwise Arithmetic
Constant space, with no additions, subtractions, multiplications, divisions, modulos or arithmetic negations:
#include <iostream>
#include <stdlib.h>
int main( int argc, char **argv ) {
for ( unsigned int value = atoi( argv[ 1 ] ); value; ) {
std::cout << value << " ";
for ( unsigned int place = 1; place; place <<= 1 )
if ( value & place ) {
value &= ~place;
break;
} else
value |= place;
}
std::cout << std::endl;
}
This is not hard. Use the modulus operator.
for (int n = 7; n <= 49; n += 7) {
print n mod 8;
}
A python version:
import sys
items = list(xrange(1, int(sys.argv[1])+1))
for i in xrange(len(items)):
print items.pop()
This is cheating, right?
#!/usr/bin/env python
def countdown(n):
for i in range(n):
print n
n = n + (n + ~n)
And just for fun, its recursive brother:
def tune_up(n):
print n
if n == 0:
return
else:
return tune_up(n + (n + ~n))
Start with a file containing descending numbers from to the max you're interested in:
7 6 5 4 3 2 1
Then... this only works up to 9999
#!/bin/sh
MAX_NUM=9999
if [ ! -e descendingnumbers.txt ]; then
seq -f%04.0f -s\ $MAX_NUM -1 1 > descendingnumbers.txt
fi
tail descendingnumbers.txt -c $[5 * $1]
Quick and dirty version in Scala:
sealed abstract class Number
case class Elem(num: Number, value: Int) extends Number
case object Nil extends Number
var num: Number = Nil
for (i <- 1 until param)
num = Elem(num, i)
while (num != null)
num match {
case Elem(n, v) => {
System.out.print(v + " ")
num = n
}
case Nil => {
System.out.println("")
num = null
}
}
Increment a signed integer passed max_int and then "Add" it to the counter... or is this consider illegitimate subtraction?
public void print (int i)
{
Console.Out.Write("{0} ", i);
int j = i;
while (j > 1)
{
int k = 1;
while (k+1 < j)
k++;
j = k;
Console.Out.Write("{0} ", k );
}
}
Kinda nasty but it does the job
public class CountUp
{
public static void main(String[] args)
{
int n = Integer.parseInt(args[0]);
while (n != 0)
{
System.out.print(n + " ");
n = (int)(n + 0xffffffffL);
}
}
}
// count up until found the number. the previous number counted is
// the decremented value wanted.
void Decrement(int& i)
{
int theLastOneWas;
for( int isThisIt = 0; isThisIt < i; ++isThisIt )
{
theLastOneWas = isThisIt;
}
i = theLastOneWas;
}
void Print(int max)
{
for( int i = max; i > 0; Decrement(i) )
{
printf("%d ", i);
}
}
Are we golfing this?
import sys
for n in reversed(range(int(sys.argv[1]))):print n+1,
#!/usr/bin/env ruby
ARGV[0].to_i.downto(1) do |n|
print "#{n} "
end
puts ''
Haskell:
import System.Environment (getArgs)
func :: Integer -> [String]
func 0 = []
func n@(x+1) = show n:func x
main = putStrLn . unwords . func . read . head =<< getArgs
A 'feature' called n+k patterns allows this: pattern matching on the addition of two numbers. It is generally not used. A more idiomatic way to do it is with this version of func:
func n = foldl (flip $ (:) . show) [] [1..n]
or, with one number per line:
import System.Environment (getArgs)
import Data.Traversable
main = foldrM (const . print) () . enumFromTo 1 . read . head =<< getArgs
Does this count? Only uses an add instruction...
int _tmain(int argc, _TCHAR* argv[])
{
int x = 10;
__asm mov eax,x;
__asm mov ebx,0xFFFFFFFF;
while (x > 0)
{
__asm add eax,ebx;
__asm mov x,eax;
__asm push eax;
printf("%d ",x);
__asm pop eax;
}
return 0;
}
Perl:
$n = $ARGV[0];
while ($n > 0) {
print "$n ";
$n = int($n * ($n / ($n+1)));
}
subtraction is an illusion anyways
I like Dylan Bennett's idea - simple, pragmatic and it adheres to the K.I.S.S principle, which IMHO is one of the most important concepts we should always try to keep in mind when we develop software. After all we write code primarily for other human beings to maintain it, and not for computers to read it. Dylan's solution in good old C:
#include <stdio.h>
int main(void) {
int n;
for (n = 7; n <= 49; n += 7) {
printf("%d ", n % 8);
}
}
In C, using a rotating memory block (note, not something I'm proud of...):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MAX 10
void rotate_array (int *array, int size) {
int tmp = array[size - 1];
memmove(array + 1, array, sizeof(int) * (size - 1));
array[0] = tmp;
}
int main (int argc, char **argv) {
int idx, max, tmp_array[MAX_MAX];
if (argc > 1) {
max = atoi(argv[1]);
if (max <= MAX_MAX) {
/* load the array */
for (idx = 0; idx < max; ++idx) {
tmp_array[idx] = idx + 1;
}
/* rotate, print, lather, rinse, repeat... */
for (idx = 0; idx < max; ++idx) {
rotate_array(tmp_array, max);
printf("%d ", tmp_array[0]);
}
printf("\n");
}
}
return 0;
}
And a common lisp solution treating lists as ints:
(defun foo (max)
(format t "~{~A~^ ~}~%"
(maplist (lambda (x) (length x)) (make-list max))))
Making this into an executable is probably the hardest part and is left as an exercise to the reader.
Common Lisp
Counting down from 7 (with recursion, or like here, using loop
and downto
):
(loop for n from 7 downto 1 do (print n))
Alternatively, perhaps a more amusing soluting. Using complex numbers, we simply add i squared repeatedly:
(defun complex-decrement (n)
"Decrements N by adding i squared."
(+ n (expt (complex 0 1) 2)))
(loop for n = 7 then (complex-decrement n)
while (> n 0) do (print n))
I like recursive
function printCountDown(int x, int y) {
if ( y != x ) printCountDown(x, y++);
print y + " ";
}
You can also use multiplication
function printNto1(int x) {
for(int y=x*(MAXINT*2+1);y<=(MAXINT*2+1);y++) {
print (y*(MAXINT*2+1)) + " ";
}
}
An alternative perl version could be:
#!/usr/local/bin/perl print reverse join(" ",1 .. $ARGV[0]) . "\n";