如何用一個循環語句輸出九九乘法表?
極限挑戰:用一條循環語句正確輸出99表!【答對贏獎】 - Java論壇 - 51CTO技術論壇_中國領先的IT技術社區
注
不能用 if switch 之類的控制語句
只是想知道怎麼只用一個 for 實現的
展示一下 C++ 17 的 fold expression:
#include &
#include &
template&
void OutputImpl(std::integer_sequence&
{
((std::cout &<&< x &<&< "*" &<&< I + 1 &<&< "=" &<&< x * (I + 1) &<&< " "), ...);
std::cout &<&< "
";
}
template&
void OutputCore(std::integer_sequence&
{
(OutputImpl(std::make_integer_sequence&
}
template&
void Output()
{
OutputCore(std::make_integer_sequence&
}
int main()
{
Output&<9&>();
}
既然大家都來答,那我也來答一個……其實另外一種思路是,給乘法表的每一個cell編號從0到45,然後構造一個函數f(n)使得這個函數返回這個編號的cell應該在哪一行那一列。注意到前N行一共有個cell,並且這個函數是在N &> 0 的時候是單調的所以於是,可以得到如下解法: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 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;
}
(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 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;
}
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);
}
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 &<&< "
";
}
}
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&
template&
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& 把 n 的值改一下就能輸出其他規格的啦~
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;
}
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&
static void print() {
std::cout &<&< x &<&< " * " &<&< y &<&< " = " &<&< std::setw(2) &<&< x * y &<&< ", ";
mul&
}
};
template&
static void print() {
std::cout &<&< x &<&< " * 9" &<&< " = " &<&< std::setw(2) &<&< x * 9 &<&< "
";
}
};
template&
static void print() {
mul&
mul2&
}
};
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&
{
typedef std::integer_sequence&
};
template &
struct ConcatAllSequence;
template &
struct ConcatAllSequence&
{
typedef std::enable_if_t&
};
template &
struct ConcatAllSequence&
{
typedef std::enable_if_t&
};
template &
struct NumberToSequenceImpl
{
typedef typename ConcatSequence&
};
template &<&>
struct NumberToSequenceImpl&<0&>
{
typedef std::integer_sequence&
};
template &
struct NumberToSequence
: NumberToSequenceImpl&
{
};
template &
struct SequenceToString;
template &
struct SequenceToString&
{
static constexpr T array[] = { Chars..., T{} };
};
template &
struct MultiplyExpression
{
typedef typename ConcatAllSequence&
};
template &
struct GenerateLineImpl
{
typedef typename ConcatAllSequence&
};
template &
struct GenerateLineImpl&
typedef typename MultiplyExpression&
};
template &
struct GenerateLine
: GenerateLineImpl&
};
template &
struct GenerateJiujiuchengfabiaoImpl
{
typedef typename ConcatAllSequence&
};
template &
struct GenerateJiujiuchengfabiaoImpl&
typedef typename GenerateLine&
};
template &
struct GenerateJiujiuchengfabiao
: GenerateJiujiuchengfabiaoImpl&
};
int main()
{
std::cout &<&< SequenceToString&
閑的。。。
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變數的值,但輸出卻沒有改變,而內存中數據的確變了,這是怎麼回事?
※如何才能自學編程並學好編程?