Программирование Загадка: отсчет без вычитания
Хорошо, цель на примере: приложение командной строки, которое делает это:
Countdown.exe 7
печатает 7 6 5 4 3 2 1
Отсутствие формы вычитания (включая использование знака минус) или строки, противоположной тому, что когда-либо разрешено.
waaaaay слишком легко, очевидно:-) Обзор ответов (по крайней мере, принципы)
- Добавлением и рекурсией
- Используя modulo
- Путем нажатия и выскакивания (возможно, наиболее очевидным?)
- Используя переполнение
- Используя пробную версию и ошибку (возможно, наименее очевидную?)
Ответы
Ответ 1
Как насчет добавления и рекурсии?
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);
}
Ответ 2
x = param;
while (x > 0) {
print x;
x = (x + param) mod (param + 1);
}
Ответ 3
Здесь вы пропустили метод, пробную версию и ошибку:
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;
}
}
}
Ответ 4
Вставьте 1-7 в стек. Поп-стек по одному. Печать 7-1.:)
Ответ 5
используйте 2 комплимента, после всего этого компьютер обрабатывает отрицательные числа.
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);
}
}
см. http://en.wikipedia.org/wiki/2's_complement
Ответ 6
Подготовьте числа в строковый буфер.
String out = "";
for (int i = 0; i < parm; i++)
{
out = " " + (i+1) + out;
}
System.out.println(out);
Ответ 7
c/С++, бит арифметического переполнения:
void Print(int max)
{
for( int i = max; i > 0; i += 0xFFFFFFFF )
{
printf("%d ", i);
}
}
Ответ 8
Я отмечаю, что никто не опубликовал самый глупый возможный ответ, поэтому я расскажу об этом:
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");
}
}
Не ненавидите меня: понимаете? Я признал, что это глупо.:)
Ответ 9
используйте ошибку округления:
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);
}
}
Ответ 10
Это не сложно. Используйте оператор модуля.
for (int n = 7; n <= 49; n += 7) {
print n mod 8;
}
Ответ 11
Побитовая арифметика
Постоянное пространство без добавок, вычитаний, умножений, делений, модулей или арифметических отрицаний:
#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;
}
Ответ 12
Версия python:
import sys
items = list(xrange(1, int(sys.argv[1])+1))
for i in xrange(len(items)):
print items.pop()
Ответ 13
Это обман, верно?
#!/usr/bin/env python
def countdown(n):
for i in range(n):
print n
n = n + (n + ~n)
И просто для удовольствия, его рекурсивный брат:
def tune_up(n):
print n
if n == 0:
return
else:
return tune_up(n + (n + ~n))
Ответ 14
Начните с файла, содержащего по убыванию числа, от максимального значения, которое вас интересует:
7 6 5 4 3 2 1
Тогда... это работает только до 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]
Ответ 15
Быстрая и грязная версия в 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
}
}
Ответ 16
Приращение целочисленного знака, переданного max_int, а затем "Добавить" его в счетчик... или это считается незаконным вычитанием?
Ответ 17
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 );
}
}
Недоброжелательно, но это делает работу
Ответ 18
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);
}
}
}
Ответ 19
// 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);
}
}
Ответ 20
Мы играем в гольф?
import sys
for n in reversed(range(int(sys.argv[1]))):print n+1,
Ответ 21
#!/usr/bin/env ruby
ARGV[0].to_i.downto(1) do |n|
print "#{n} "
end
puts ''
Ответ 22
Haskell:
import System.Environment (getArgs)
func :: Integer -> [String]
func 0 = []
func [email protected](x+1) = show n:func x
main = putStrLn . unwords . func . read . head =<< getArgs
Функция A ', называемая n + k паттернами, позволяет это: сопоставление шаблонов при добавлении двух чисел. обычно не используется. Более идиоматический способ сделать это с помощью этой версии func:
func n = foldl (flip $ (:) . show) [] [1..n]
или, с одним номером на строку:
import System.Environment (getArgs)
import Data.Traversable
main = foldrM (const . print) () . enumFromTo 1 . read . head =<< getArgs
Ответ 23
Считается ли это? Использует только команду добавления...
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;
}
Ответ 24
Perl:
$n = $ARGV[0];
while ($n > 0) {
print "$n ";
$n = int($n * ($n / ($n+1)));
}
Ответ 25
вычитание - это иллюзия в любом случае
Ответ 26
Мне нравится идея Дилана Беннета - простая, прагматичная и придерживается принципа K.I.S.S, который ИМХО - одна из самых важных концепций, которые мы всегда должны стараться иметь в виду при разработке программного обеспечения. В конце концов, мы пишем код прежде всего для других людей, чтобы поддерживать его, а не для компьютеров, чтобы его прочитать. Решение Дилана в старом добром C:
#include <stdio.h>
int main(void) {
int n;
for (n = 7; n <= 49; n += 7) {
printf("%d ", n % 8);
}
}
Ответ 27
В C, используя вращающийся блок памяти (обратите внимание, что я не горжусь...):
#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;
}
И общее решение lisp, обрабатывающее списки как ints:
(defun foo (max)
(format t "~{~A~^ ~}~%"
(maplist (lambda (x) (length x)) (make-list max))))
Включение этого в исполняемый файл, вероятно, является самой сложной частью и остается как упражнение для читателя.
Ответ 28
Общий Lisp
Подсчитайте с 7 (с рекурсией или как здесь, используя loop
и downto
):
(loop for n from 7 downto 1 do (print n))
Альтернативно, возможно, более забавное растворение. Используя комплексные числа, мы просто добавляем квадрат i:
(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))
Ответ 29
Мне нравится рекурсивный
function printCountDown(int x, int y) {
if ( y != x ) printCountDown(x, y++);
print y + " ";
}
Вы также можете использовать умножение
function printNto1(int x) {
for(int y=x*(MAXINT*2+1);y<=(MAXINT*2+1);y++) {
print (y*(MAXINT*2+1)) + " ";
}
}
Ответ 30
Альтернативная версия perl может быть:
#!/usr/local/bin/perl
print reverse join(" ",1 .. $ARGV[0]) . "\n";