Ruby
どう書く
yhpg
C言語

オフラインリアルタイムどう書く F09 の問題をRubyとC言語で解いた

問題: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" );
}