如何用一個循環語句輸出九九乘法表?

極限挑戰:用一條循環語句正確輸出99表!【答對贏獎】 - Java論壇 - 51CTO技術論壇_中國領先的IT技術社區

不能用 if switch 之類的控制語句

只是想知道怎麼只用一個 for 實現的


展示一下 C++ 17 的 fold expression:

#include &
#include &

template&
void OutputImpl(std::integer_sequence&, int x)
{
((std::cout &<&< x &<&< "*" &<&< I + 1 &<&< "=" &<&< x * (I + 1) &<&< " "), ...); std::cout &<&< " "; } template&
void OutputCore(std::integer_sequence&)
{
(OutputImpl(std::make_integer_sequence&{}, I + 1), ...);
}

template&
void Output()
{
OutputCore(std::make_integer_sequence&{});
}

int main()
{
Output&<9&>();
}


既然大家都來答,那我也來答一個……其實另外一種思路是,給乘法表的每一個cell編號從0到45,然後構造一個函數f(n)使得這個函數返回這個編號的cell應該在哪一行那一列。

注意到前N行一共有sum^N_{i=1}i = {1 over 2}(N^2 + N)個cell,並且這個函數是在N &> 0 的時候是單調的

所以

row = [{sqrt{8n + 1} + 1 over 2}]

col = n + 1 - {(row - 1) row over 2}

於是,可以得到如下解法:

Python

import math
R = map(lambda x: (int( (math.sqrt( 8 * x + 1 ) + 1) / 2), x),range(0,45))
RC = map(lambda x: (x[0], x[1] + 1 - (x[0] - 1) * x[0] / 2), R)
T = map(lambda x: ("%d*%d=%d"%(x[1],x[0],x[0]*x[1]) + ("
" if(x[0]==x[1]) else " ")), RC)
print "".join(T)

C

#include &
#include & int main()
{
int i;
for(i = 0; i &< 45; i ++) { int R = (sqrt(8 * i + 1) + 1) / 2; int C = i + 1 - (R - 1) * R / 2; printf("%d*%d=%d", C, R, R * C); putchar(R == C ? " " : " "); } return 0; }

Scala

(0 to 44) map (x =&> {
val r = ((Math.sqrt(x * 8 + 1) + 1 ) / 2).toInt;
val c = x + 1 - (r - 1) * r / 2;
"%d*%d=%d%s".format(c,r,r*c, if(r==c)"
" else " ")
}) mkString ""

===

再補充一個混亂版的,既然大家都想寫得短

#include &
#include & int r,c;
int main(int i)
{
return r=(sqrt(8*i-7)+1)/2,c=i-(r-1)*r/2,printf("%d*%d=%d%c",c,r,c*r,32-22*(r==c)),i-45main(i + 1);
}

=== 再更,既然有人質疑不能用SQRT,那麼只好祭出大殺器Fast inverse square root

float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;

x2 = number * 0.5F;
y = number;
i = * ( long * ) y; // evil floating point bit level hacking
i = 0x5f3759df - ( i &>&> 1 ); // what the fuck?
y = * ( float * ) i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

return y;
}

但是這段代碼是算1/sqrt(x)的,怎麼辦?其實前面幾行是估算1/sqrt(x)的值,這一段可以用,然後我們有牛頓迭代法 x_{n+1} = frac{x_n + frac{N}{x_n}}{2} = frac{1}{2y_n} + 2Ny_n其中 y_n = frac{1}{x_n}

float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;

x2 = number * 0.5F;
y = number;
i = * ( long * ) y; // evil floating point bit level hacking
i = 0x5f3759df - ( i &>&> 1 ); // what the fuck?
y = * ( float * ) i;
return 1.0F / (2 * y) + x2 * y;
}

把這段代碼壓縮成緊湊的形式

union { float f; long l; } v;
void s(float t)
{
t = v.f/2,v.l=0x5f3759df-v.l/2,v.f=0.5/v.f+t*v.f;
}

然後替換sqrt函數

#include &
union { float f; long l; } v;
int r,c;
void s(float t)
{
t = v.f/2,v.l=0x5f3759df-v.l/2,v.f=0.5/v.f+t*v.f;
}
int main(int i)
{
return v.f=8*i-7,s(0),r=(v.f+1)/2,c=i-(r-1)*r/2,printf("%d*%d=%d%c",c,r,c*r,32-22*(r==c)),i-45main(i + 1);
}

最後增加一個終極蛋疼版

#include &
union { float f; long l; } v;
int r,c;
int main(int i)
{
return v.f = 8*i-7,v.l=0x5f3759df-v.l/2,r=0.5+0.25/v.f+(2*i-1.75)*v.f,c=i-(r-1)*r/2,printf("%d*%d=%d%c",c,r,c*r,32-22*(r==c)),i-45main(i + 1);
}

或者模仿IOCCC來一個

union
{float f;
long l;}v;int
r,c;int main(int
i){return v.f=8*i-7,
v.l=0x5f3759df-v.l/2,r=
0.5+0.25/v.f+(2*i-1.75)*v.f,
c=i-(r-1)*r/2,printf("%d*%d=%d"
"%c",c,r,c*r,32-22*(r==c)),i-45main(i+1);}


MATLAB:

&>&> for k = 1 : 9, disp((1 : k) * k), end
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72 81

如果不必須有循環可以用 arrayfun:

arrayfun(@(k) disp((1 : k) * k), 1 : 9)

--------更新--------

如果需要帶表達式,也是類似的:

&>&> for k = 1 : 9, disp(join(string(k) + "*" + (1 : k) + "=" + (1 : k) * k)), end
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

同樣可以改寫為:

arrayfun(@(k) disp(join(string(k) + "*" + (1 : k) + "=" + (1 : k) * k)), 1 : 9)


matlab 自帶矩陣計算功能,利用線性代數的相關知識,甚至能夠更進一步,根本不需要任何循環語句。兩行代碼,就可以解決這個問題。

首先構造一個行矩陣:

a = [1: 9];

然後利用矩陣的乘法,讓 a 的轉置矩陣 和 a 相乘:

disp(a" * a);

輸出:

問題解決。


寫一個虛擬機解釋器,剛好一個大循環……

有根據棧頂跳轉的功能就可以了

const PUSH = n =&> vm =&> (vm.s.push(n), vm.ip++)
const ADD = vm =&> (vm.s.push(vm.s.pop() + vm.s.pop()), vm.ip++)
const JMP = vm =&> (vm.ip = vm.s.pop())
const DUP = vm =&> {let a = vm.s.pop(); vm.s.push(a, a); vm.ip++)
const SWAP = vm =&> {let a = vm.s.pop(); let b = vm.s.pop(); vm.s.push(b); vm.s.push(a); vm.ip++}
const READ = slot =&> vm =&> (vm.s.push(vm.mem[slot]), vm.ip++)
const WRITE = slot =&> vm =&> (vm.mem[slot] = vm.s.pop(), vm.ip++)
const EXOTIC = fn =&> vm =&> (fn(vm.s.pop()), vm.ip++)

...

var vm = {s: [], mem:[], ip:0, prog: ...}
while(vm.prog[vm.ip]) vm.prog[vm.ip](vm);


t = """1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
"""

for i in [0]:
print(t)


原題主還能再無聊點么,參考答案號稱「此題是考思想的」,你這思想可夠深刻的

為了避免重複製造輪子,我們應該盡量復用標準庫,簡單的數組循環還要手寫么?

#include &
#include &
#include &

using namespace std;

void work (int n) {
int a[n + 1], b[n + 1];
for (int i = 1; i &<= n; i ++) { a[i] = i * i; b[i] = i; transform (a + 1, a + i, b + 1, a + 1, plus&());
copy (a + 1, a + i + 1, ostream_iterator& (cout, " "));
cout &<&< " "; } } int main () { int n; cin &>&> n;
work (n);
}

我想,這個符合條件吧。

然後我還寫了個稍微簡單點的

#include &
using namespace std;

int main () {
int n;
scanf ("%d", n);

for (int x[2] = {1, 1};
x[0] &<= n; x[1] ++, x[1] -= (x[1] - 1) * (x[1] &> x[0]),
x[0] += x[1] == 1)
printf ("%d%c", x[0] * x[1], "
"[x[0] == x[1]]);
}

看起來沒啥問題。

等下,不是。

「一行一行print結果的無效」

完了,所有輸出的時候沒刷緩衝區的都不對。

Fun fact: 不是所有編程語言都有循環。

不是所有編程語言都有語句!!!!!!

(read &<$&> getLine :: IO Int) &>&>=
-&> mapM_ (i -&> putStrLn . unwords $ show . (i*) &<$&> [1..i]) [1..n]

(Fun fact:這不是亂七八糟的代碼。這是邏輯特別清晰明了的 Haskell。)

好像有人沒找到原題主的「一個好的演算法首先是簡單易懂的,其次是清晰明了的,再個一定是充滿美感的」的代碼。我貼一下,不多做評論

public class Test99 {
public static void main(String[] args) {
Iterator.iterate(5,new IAction());
}
}
abstract class Iterator& {
abstract void process(T n);
static void iterate(int n, Iterator action) {
for (int i = 1; i &<= n; i++) { action.process(i); } } } class IAction extends Iterator& {
public void process(Integer n) {
iterate(n, new JAction(n));
System.out.println();
}
}
class JAction extends Iterator& {
private final int x;
JAction(int n) {
this.x = n;
}
public void process(Integer n) {
System.out.print(" "+x * n);
}
}

考你 mb 的思想!!!!!!(←中心句)

附贈一個 for 的星星三角形,至少這個還比 Iterator 有思想一些

#include &
using namespace std;

char buf[2000];

int main () {
int n;
scanf ("%d", n);
for (int i = 0; i &< n; i ++) { buf[i] = "*"; puts (buf); } }


題主限制了一個for循環,不讓用if等判斷,但是自己用了iter,只是把循環和判斷隱藏了而已,這種就是典型的閑的蛋疼的問題

那我索性來個沒有任何循環的版本吧,加上import,只有3行代碼

看,還提供最後總結評價喲~

PS: 我也是閑的蛋疼,這種代碼玩兒玩兒可以,不要學~

受 @zpan @夏之幻想 啟發,來個更簡版模版編程

```C++

#include &

template& struct F99{

static void print(){

F99&::print();

std::cout &<&< x &<&< "*" &<&< y &<&< " = " &<&< x*y &<&< " ";

}};

template& struct F99&<1, y&>{

static void print(){

F99&::print();

std::cout &<&< " 1*" &<&< y &<&< " = " &<&< y &<&< " ";

}};

template&<&> struct F99&<1, 1&>{

static void print(){

std::cout &<&< "1*1 = 1";

}};

int main(void)

{

F99&<9, 9&>::print();

return 0;

}


這個嘛,用 Haskell 的話一行就可以搞定了

Prelude&> printTable = sequence_ . map ((*&> putChar "
") . (sequence_ . map ((*&> putChar " ") . putStr . show) . (&<*&>) take ((+) &>&>= iterate))) . ($ iterate succ 1) . take
Prelude&> :t printTable
printTable :: Int -&> IO ()
Prelude&> printTable 9
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72 81
Prelude&>

這個是嚴格只用 Prelude 提供的東西實現的。不過 Prelude 裡面真的沒有提供循環語句啊(攤手


-module (nn).
-export ([make_nn/1]).

make_line(L, L) -&>
io:format("~w * ~w = ~w
", [L, L, L * L]);

make_line(L, R) -&>
io:format("~w * ~w = ~w ", [L, R, L * R]),
make_line(L, R + 1).

make_nn(Max, Max) -&>
make_line(Max, 1);

make_nn(N, Max) -&>
make_line(N, 1),
make_nn(N + 1, Max).

make_nn(Max) -&>
make_nn(1, Max).


用庫用 generator 什麼的太簡單,就不給了,遞歸解法也略過。

先來個最基本的解法,中學數學:

n = 9

for i in range(n * (n + 1) // 2):
line = int(((8 * i + 1) ** 0.5 - 1)) // 2

x = i - line * (line + 1) // 2 + 1
y = line + 1

print(str(x) + "*" + str(y) + "=" + str(x * y), end=chr(10 + 22 * int(x != y)))

然後可以用各種 trick 做,慢慢填坑——

比如跳轉表:

n = 9

for i in range(n * n):
x = i % n + 1
y = i // n + 1

a = lambda: print(str(x) + "*" + str(y) + "=" + str(x * y), end=chr(10 + 22 * int(x != y)))
b = lambda: 1
[a, b][int(x &> y)]()

比如 exec (用法:把這個文件餵給 shell):

#if 0
cc $0 -o ./m
./m ./m ./m ./m ./m ./m ./m ./m ./m echo -n
exit
#endif

#include &
#include &
#include &
#include &
#include &

int main(int argc, char **argv) {
int n = argc - 2;

fork() || execvp(argv[1], argv + 1);
wait(NULL);

for (int i = 0; i &< n; ++i) { printf("%d*%d=%d", i + 1, n, (i + 1) * n); putchar(10 + 22 * (i + 1 != n)); } }

(慢慢填坑


知乎果然是程序猿的天下呢!

我們這些不經常寫程序的人難道沒有發言的權利了嗎!

哼!

我的答案是

=IF(B$1&<=$A2,B$1"×"$A2"="B$1*$A2,"")

用Excel實現

在B2輸入公式,右拉,下拉

搞定!

那個,弱弱的問一句,excel公式,也應該算語句吧^

相關Live

* 培養數據分析的思維方式

相關回答

* 怎麼培養數據分析的能力? - 知乎

* 業餘時間如何學數據分析? - 知乎

* 零基礎如何學爬蟲技術? - 知乎

* Excel 有什麼神奇用途? - 知乎

-------分割線-------
歡迎關注我的微信公眾賬號:決明子 Jueming_zi
這裡有關於攝影,繪畫,藝術,以及我想說給你們聽的故事

http://weixin.qq.com/r/iUgiOm3EeDAHrSlZ9x2b (二維碼自動識別)


參考了 @Belleve 的想法,自己隨便設計了一個虛擬機(C++11):

#include &
#include &
#include &

struct VM { std::stack& stack; std::vector&&> program; int mem[256]; int ip = 0; };
enum Op { End, Push, Pop, Store, Load, Add, Mul, Neg, Jmp, JmpZ, PutC, PutN };
using OpFunc = void (*)(VM, int);
OpFunc ops[] = {
nullptr,
[](VM vm, int a) { vm.stack.push(a); ++vm.ip; },
[](VM vm, int a) { vm.stack.pop(); ++vm.ip; },
[](VM vm, int a) { vm.mem[a] = vm.stack.top(); ++vm.ip; },
[](VM vm, int a) { vm.stack.top() = vm.mem[a]; ++vm.ip; },
[](VM vm, int a) { a = vm.stack.top(); vm.stack.pop(); vm.stack.top() += a; ++vm.ip; },
[](VM vm, int a) { a = vm.stack.top(); vm.stack.pop(); vm.stack.top() *= a; ++vm.ip; },
[](VM vm, int a) { vm.stack.top() = -vm.stack.top(); ++vm.ip; },
[](VM vm, int a) { vm.ip = a; },
[](VM vm, int a) { vm.ip = !vm.stack.top() * a + !!vm.stack.top() * (vm.ip + 1); vm.stack.pop(); },
[](VM vm, int a) { std::cout &<&< (char)vm.stack.top(); ++vm.ip; }, [](VM vm, int a) { std::cout &<&< vm.stack.top(); ++vm.ip; }, }; int main() { const int n = 9; VM vm; vm.program = { {Push, 1}, {Store, 0}, {Pop, 0}, {Push, 1}, {Store, 1}, {Pop, 0}, {Push, 0}, {Load, 0}, {Push, 0}, {Load, 1}, {Mul, 0}, {PutN, 0}, {Pop, 0}, {Push, " "}, {PutC, 0}, {Pop, 0}, {Push, 0}, {Load, 0}, {Push, 0}, {Load, 1}, {Neg, 0}, {Add, 0}, {JmpZ, 30}, {Push, 0}, {Load, 1}, {Push, 1}, {Add, 0}, {Store, 1}, {Pop, 0}, {Jmp, 6}, {Push, " "}, {PutC, 0}, {Pop, 0}, {Push, 0}, {Load, 0}, {Push, n}, {Neg, 0}, {Add, 0}, {JmpZ, 46}, {Push, 0}, {Load, 0}, {Push, 1}, {Add, 0}, {Store, 0}, {Pop, 0}, {Jmp, 3}, {End, 0}, }; for(; vm.program[vm.ip].first != End; ) { auto x = vm.program[vm.ip]; ops[x.first](vm, x.second); } return 0; }

把 n 的值改一下就能輸出其他規格的啦~

說實話這題確實挺無聊的(逃


s=str()

sp="(這裡是8個空格)
"

for i in xrange(81):

....s+=str(i%9+1)+"*"+str((i-i%9)/9+1)+"="+

str((i%9+1)*((i-i%9)/9+1))+sp[i%9]

print s

還有更爽的

print str.join("",[str((i-i%9)/9+1)+"*"+str(i%9+1)+"="+str((i%9+1)*((i-i%9)/9+1))+"
"[i%9] for i in xrange(80)])


來個 C++ 模板元編程,一個循環和條件判斷都沒有,除了輸出以外沒用任何庫:

#include &
#include &

template& struct mul {
static void print() {
std::cout &<&< x &<&< " * " &<&< y &<&< " = " &<&< std::setw(2) &<&< x * y &<&< ", "; mul&::print();
}
};

template& struct mul& {
static void print() {
std::cout &<&< x &<&< " * 9" &<&< " = " &<&< std::setw(2) &<&< x * 9 &<&< " "; } }; template& struct mul2 {
static void print() {
mul&::print();
mul2&::print();
}
};

template&<&> struct mul2&<9&> {
static void print() {
mul&<9, 9&>::print();
}
};

int main() {
mul2&<1&>::print();
return 0;
}


看了原貼發現不過是利用了標準庫,MATLAB表示不服:

n = 9;
[X, Y] = meshgrid(1:n);
Z = X .* Y;
S = nan(n);
L = logical(tril(Z));
S(L) = Z(L);
S = strtrim(strrep(cellstr(num2str(S, "%4d")), "NaN", " "));
fprintf("%s
",S{:});


def table(n)
n = (n - 1) * 10 + n
1.upto(n) do |i|
a, b = format("%2d", i).split("")
a = a.to_i + 1
b = b.to_i

print ("#{a-b}:" + format("%2d", a * b) + " ").gsub(/^-d:s?d+/, "").gsub(/^d:/, "").gsub(/^s?0 $/, "
")
end
puts
end


我來搗個亂【

編譯期生成⑨⑨表,不過一個循環語句都沒用【

#include &
#include &

template &
struct IsSequence
: std::false_type
{
};

template &
struct IsSequence&&>
: std::true_type
{
};

template &
struct ConcatSequence;

template &
struct ConcatSequence&, std::integer_sequence&&>
{
typedef std::integer_sequence& type;
};

template &
struct ConcatAllSequence;

template &
struct ConcatAllSequence&
{
typedef std::enable_if_t&::value, typename ConcatSequence&::type&>::type&> type;
};

template &
struct ConcatAllSequence&
{
typedef std::enable_if_t&::value, last&> type;
};

template &
struct NumberToSequenceImpl
{
typedef typename ConcatSequence&::type, std::integer_sequence&&>::type type;
};

template &<&>
struct NumberToSequenceImpl&<0&>
{
typedef std::integer_sequence& type;
};

template &
struct NumberToSequence
: NumberToSequenceImpl&
{
};

template &
struct SequenceToString;

template &
struct SequenceToString&&>
{
static constexpr T array[] = { Chars..., T{} };
};

template &
struct MultiplyExpression
{
typedef typename ConcatAllSequence&, typename NumberToSequence&::type, std::integer_sequence&, typename GenerateLineImpl&::type&>::type type;
};

template &
struct GenerateLineImpl& {
typedef typename MultiplyExpression&::type type;
};

template &
struct GenerateLine
: GenerateLineImpl& {
};

template &
struct GenerateJiujiuchengfabiaoImpl
{
typedef typename ConcatAllSequence&::type, std::integer_sequence&, typename GenerateJiujiuchengfabiaoImpl&::type&>::type type;
};

template &
struct GenerateJiujiuchengfabiaoImpl& {
typedef typename GenerateLine&::type type;
};

template &
struct GenerateJiujiuchengfabiao
: GenerateJiujiuchengfabiaoImpl& {
};

int main()
{
std::cout &<&< SequenceToString&::type&>::array &<&< std::endl; }


閑的。。。

print "
".join([" ".join([str(i * j) for i in xrange(1,j+1)]) for j in xrange(1,10)])

更是閑的。。。

let str = (1..&<10) .map { i in (1..&


c++的,這應該是一個數學問題吧orz

#include&
using namespace std;
int main()
{
int n=9;//n*n的乘法表
for(int i=1,a=1,b=1,t=1;i&<=n*(n+1)/2;++i,++a) { a=a*!!(t-a)+!(t-a); t+=!(a-1); cout&<&


推薦閱讀:

計算機應屆生找工作前去實習真的很重要嗎?
C++無法取代C嗎?
如何看待C++前置聲明?
C++中改變了const變數的值,但輸出卻沒有改變,而內存中數據的確變了,這是怎麼回事?
如何才能自學編程並學好編程?

TAG:程序員 | 編程 | 計算機 | Java編程 | 數據結構 |