challenge 文字列からの情報抽出

与えられた文字列から特定の条件を満たす文字列を抽出するコードを書いてください。 状況としてはテキスト形式で渡された原稿の中から、画像のファイル名を抽出するようなものをイメージしてください。

サンプル入力

aaa abc-hidden.png>hoge-big.jpeg
---foo-hidden-small.gif|^_^a.bmp
--hiddena-hoge.png<=not hidden~~
--small.jpg<=not small(^_^)
normal-small-big.hoge

サンプル出力

name:'abc', ext:'png', size: normal hidden: True
name:'hoge', ext:'jpeg', size: big hidden: False
name:'foo', ext:'gif', size: small hidden: True
name:'a', ext:'bmp', size: normal hidden: False
name:'hoge', ext:'png', size: normal hidden: False
name:'small', ext:'jpg', size: normal hidden: False
name:'small', ext:'hoge', size: big hidden: False

探すべき文字列は下の条件を満たします

  • アルファベットと1個のピリオド、ハイフンで構成される
  • 前後にはアルファベットではない文字がある(abcd.jpgがaaaabcd.jpghogeなどと書かれていることはない)
  • ピリオドの後ろは拡張子で、アルファベットだけで構成されている
  • ピリオドの直前に-hidden, -small, -bigがある場合には特殊な意味がある。複数個ある場合(a-hidden-big.jpgなど)も同じ
  • ファイル名に-hiddenと-smallまたは-hiddenと-bigの両方が含まれる場合は-hiddenの方が先にある
  • 特殊な意味の-hidden, -small, -big以外でハイフンが使われることはない
  • 特殊な意味の-smallと-bigの両方が付くことはない

出力は以下の条件を満たす必要があります

  • ファイル名が出現した順に表示される
  • ファイル名に-hiddenが含まれるかどうかを真偽値で表示する
  • ファイル名に-smallまたは-bigが含まれる場合はsmallまたはbigと、含まれない場合はnormalと表示する
  • -hidden, -small, -bigを取り除いたファイル名部分と、拡張子を表示する

このお題は、正規表現のグループに名前をつけて連想配列として取得できるPythonからの挑戦状です。

Posted feedbacks - C++

正規表現使わないと結構面倒ですね。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <iterator>
#include <ctype.h> // isalpha()

struct is_alpha : public std::unary_function<char, bool>
{
    bool operator()(char c) const
    {
        return isalpha(c);
    }
};

bool option(
    std::string::const_iterator beg,
    std::string::const_iterator& it,
    const std::string& name,
    std::string& ret)
{
    const std::string s = "-" + name;

    if (std::distance(beg, it) >= s.size() && std::equal(it - s.size(), it, s.begin()))
    {
        it -= s.size();

        ret = name;

        return true;
    }
    else
    {
        return false;
    }
}

void extract(const std::string& s)
{
    std::string::const_iterator it = s.begin();

    while ((it = std::find(it, s.end(), '.')) != s.end())
    {
        std::string::const_iterator it2;

        it2 = std::find_if(it + 1, s.end(), std::not1(is_alpha()));

        const std::string ext(it + 1, it2);

        std::string size, hidden;

        it2 = it;

        option(s.begin(), it2, "big", size) || option(s.begin(), it2, "small", size);

        option(s.begin(), it2, "hidden", hidden);

        std::string name(
            std::find_if(
                std::string::const_reverse_iterator(it2),
                s.rend(),
                std::not1(is_alpha())
            ).base(), it2
        );

        if (name.empty())
        {
            if (!hidden.empty())
            {
                name.swap(hidden);
            }
            else if (!size.empty())
            {
                name.swap(size);
            }
        }

        if (size.empty())
        {
            size = "normal";
        }

        std::cout
            << "name:'" << name << "', "
            << "ext:'" << ext << "', "
            << "size: " << size << " "
            << "hidden: " << (!hidden.empty())
            << std::endl;

        ++it;
    }
}

int main()
{
    std::boolalpha(std::cout);

    extract(
        "aaa abc-hidden.png>hoge-big.jpeg\n"
        "---foo-hidden-small.gif|^_^a.bmp\n"
        "--hiddena-hoge.png<=not hidden~~\n"
        "--small.jpg<=not small(^_^)\n"
        "normal-small-big.hoge\n"
    );
}

Index

Feed

Other

Link

Pathtraq

loading...