問題:http://nabetani.sakura.ne.jp/hena/ordf09rotbox/
解答集:https://qiita.com/Nabetani/items/61e13fa5cf0abe5979be
RubyとC言語で解答しました。
Rubyは長ったらしくてかっこわるい感じになってしまった。
f09_2.rb
def calc(src)
a = '123456789'.chars
yoko = proc do |i, t|
next if t.nil?
x = i % 3 + t * 3
y = (i + 1) % 3 + t * 3
a[x], a[y] = a[y], a[x]
end
tate = proc do |i, t|
next if t.nil?
x = i * 3 + t
y = ((i + 1) % 3) * 3 + t
a[x], a[y] = a[y], a[x]
end
src.chars.each do |c|
2.times { |i| yoko.call(i, 'abc'.index(c)) }
2.times.reverse_each { |i| tate.call(i, 'def'.index(c)) }
2.times.reverse_each { |i| yoko.call(i, 'ghi'.reverse.index(c)) }
2.times { |i| tate.call(i, 'jkl'.reverse.index(c)) }
end
a.each_slice(3).to_a.map(&:join).join('/')
end
DATA.each do |d|
n, src, exp, _link = d.split
act = calc src
puts %(#{n} #{exp} != #{act}) unless act == exp
end
__END__
0 aegj 286/435/971 リンク
1 a 231/456/789 リンク
同じアルゴリズムをC言語でも実装しました。
f09.c
# include <stdio.h>
# include <string.h>
void swap(char * a, char * b)
{
char t = *a;
*a = *b;
*b = t;
}
void calc(const char * src, char * act)
{
char a[] = "123456789";
for(const char * ch = src; *ch; ++ch) {
int i = (*ch - 'a') % 3;
char *c1, *c2, *c3;
if(*ch <= 'c') { // abc
c1 = a + i * 3;
c2 = c1 + 1;
c3 = c2 + 1;
} else if(*ch <= 'f') { // def
c1 = a + i + 6;
c2 = c1 - 3;
c3 = c2 - 3;
} else if(*ch <= 'i') { // ghi
c1 = a + (2 - i) * 3 + 2;
c2 = c1 - 1;
c3 = c2 - 1;
} else if(*ch <= 'l') { //jkl
c1 = a + (2 - i);
c2 = c1 + 3;
c3 = c2 + 3;
}
swap(c1, c2);
swap(c2, c3);
}
act[3] = act[7] = '/';
memcpy(act, a, 3);
memcpy(act + 4, a + 3, 3);
memcpy(act + 8, a + 6, 3);
}
void test(const char * src, const char * exp)
{
char act[12] = { 0 };
calc(src, act);
if(strcmp(exp, act)) {
printf("%s != %s (%s)\n", exp, act, src);
}
}
int main(void)
{
/*0*/ test( "aegj", "286/435/971" );
/*1*/ test( "a", "231/456/789" );
/*2*/ test( "e", "183/426/759" );
/*3*/ test( "g", "123/456/978" );
/*4*/ test( "j", "126/459/783" );
/*5*/ test( "bb", "123/645/789" );
/*6*/ test( "jjj", "123/456/789" );
/*7*/ test( "bd", "723/164/589" );
/*8*/ test( "ah", "231/645/789" );
/*9*/ test( "bj", "124/569/783" );
}
鍋谷さんのPythonをC言語で実装
f09_2.c
# include <stdio.h>
# include <string.h>
int const table[][6] = {
{1,2,3,2,3,1},//a
{4,5,6,5,6,4},//b
{7,8,9,8,9,7},//c
{1,4,7,7,1,4},//d
{2,5,8,8,2,5},//e
{3,6,9,9,3,6},//f
{7,8,9,9,7,8},//g
{4,5,6,6,4,5},//h
{1,2,3,3,1,2},//i
{3,6,9,6,9,3},//j
{2,5,8,5,8,2},//k
{1,4,7,4,7,1},//l
};
void calc(const char * src, char * act)
{
char a[] = "123456789";
for(const char * ch = src; *ch; ++ch) {
const int *b = table[*ch - 'a'];
char t0 = a[b[3] - 1];
char t1 = a[b[4] - 1];
char t2 = a[b[5] - 1];
a[b[0] - 1] = t0;
a[b[1] - 1] = t1;
a[b[2] - 1] = t2;
}
act[3] = act[7] = '/';
memcpy(act, a, 3);
memcpy(act + 4, a + 3, 3);
memcpy(act + 8, a + 6, 3);
}
void test(const char * src, const char * exp)
{
char act[12] = { 0 };
calc(src, act);
if(strcmp(exp, act)) {
printf("%s != %s (%s)\n", exp, act, src);
}
}
int main(void)
{
/*0*/ test( "aegj", "286/435/971" );
/*1*/ test( "a", "231/456/789" );
/*2*/ test( "e", "183/426/759" );
/*3*/ test( "g", "123/456/978" );
/*4*/ test( "j", "126/459/783" );
/*5*/ test( "bb", "123/645/789" );
/*6*/ test( "jjj", "123/456/789" );
/*7*/ test( "bd", "723/164/589" );
/*8*/ test( "ah", "231/645/789" );
/*9*/ test( "bj", "124/569/783" );
}