正则表达式来匹配不可分的分数 [英] regex to match irreducible fractions

查看:95
本文介绍了正则表达式来匹配不可分的分数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将不可分割的分数与正则表达式匹配?



例如23/25,3/4,5/2,100/101等。首先,我不知道关于正则表达式中的gcd-algorithm实现。



更新,对于所有回答您正在使用错误工具的人:



是的,伙计们,我正在实现正常情况下使用的正则表达式。没关系。但是,这个问题很奇怪是它的一个重点。



更新2:这个想法是找到一个可能有用的正则表达式例如:

  $>回声1/2| grep -P正则表达式
1/2
$>回声2/4| grep -P正则表达式

所以,正则表达式应该只是一个字符串,而不使用任何脚本和变量。只有正则表达式。



实际上,我已经知道一些正则表达式匹配一元数字系统中可缩减的分数。

  $>回声11/1111| grep -P'^ 1/1 + $ |(11 +)+ \ 1 + / \ 1 + $'
11/1111

所以事情是在正则表达式中将十进制转换为一元数字系统,但我不知道如何。

解决方案

UPDATE



由于海报请求一个与36/270字符串匹配的单一正则表达式,这个正则表达式是多么的清晰,这个正则表达式是:

$ $ $ $ $ $ $ $ code $ ?。\\d +)$(({(1×$ 1 / 1×$ 2)=〜米{^(|θ1 + /(1)|(11+)\1 * / \1 +)$ }})| ^)};

但是,如果像我一样,您认为一个难以辨认的正则表达式是绝对不可接受的,那么您会写更多可读性为:

  my $ reduceable_rx = qr {
#首先匹配一个分数:
^(\\ ($($ 1。$。/。1 x $ 2)=〜m {$ b $ $
#$
# b ^
(?| 1+ /(1)#平凡情况:GCD = 1
|(11+)\ 1 * / \ 1 +#找到GCD
)$ (* PASS)
| ^#更便携版本(* FAIL)
)$(



$ b $) b $ b} x;

您可以通过将与一元版本匹配的版本与匹配十进制的版本分开来提高可维护性这样的版本:

 #这个假设一元符号
my $ unary_rx = qr {
^
(?| 1+ /(1)
|(11+)\ 1 * / \ 1 +

$
} x;

#这个假设小数表示法并在内部转换
my $ decimal_rx = qr {
#首先匹配一个分数:
^(\ d +)/(\\ \\ d +)$
#现在用于硬件:
(?(?{(1 x $ 1。/。1 x $ 2)=〜$ unary_rx})
#更便携(* PASS)
| ^#的更多便携式版本(* FAIL)

} x;

将它分成两个命名的正则表达式并不那么容易?那现在可以使 $ reducible_rx $ decimal_rx 相同,但是一元版本是它自己的东西。我就是这样做的,但是原始的海报需要一个单一的正则表达式,所以你必须插入嵌套的那个,就像我上面第一次出现的一样。



你可以使用以下方式插入下面的测试工具:

  if($ frac =〜$ reduced_rx){
cmp_ok($ frac,ne,reduce($ i,$ j),$ i / $ j是$ test);
} else {
cmp_ok($ frac,eq,reduce($ i,$ j),$ i / $ j是$ test);
}

你会看到它是一个正确的正则表达式,它通过了所有的测试,因此,此外,使用单一的正则表达式,因此现在已经通过了原始问题的所有要求,我宣布Q\"ᴜᴏᴅᴇʀᴀᴛsᴛʀᴀɴᴅᴜᴍ:退出,已经足够了。

How can I match irreducible fractions with regex?

For example, 23/25, 3/4, 5/2, 100/101, etc.

First of all, I have no idea about the gcd-algorithm realization in regex.

Update for all of you who's answering like "You are using the wrong tool":

Yeah, guys, I'm realizing what regex is normally used for. It's okay. But that this question is weird is kind of its whole point.

Updated 2: The idea is to find a regex that could be helpful in a situation like:

$> echo "1/2" | grep -P regex
1/2
$> echo "2/4" | grep -P regex

So, the regex should be only a string, without using any scripts and variables. Only regex.

Actually, I already know some regex which match reducible fractions written in the unary number system.

$> echo "11/1111" | grep -P '^1/1+$|(11+)+\1+/\1+$'
11/1111

So the thing is to convert from decimal to unary number system in regex, but I don't know how.

解决方案

UPDATE

Since the poster requested a single regex that matches against strings like "36/270", but says it doesn’t matter how legible it is, that regex is:

my $reducible_rx = qr{^(\d+)/(\d+)$(?(?{(1x$1."/".1x$2)=~m{^(?|1+/(1)|(11+)\1*/\1+)$}})|^)};

But, if like me, you believe that an illegible regex is absolutely unacceptable, you will write that more legibly as:

my $reducible_rx = qr{
  # first match a fraction:
    ^ ( \d+ ) / ( \d+ ) $
  # now for the hard part:
    (?(?{ ( 1 x $1 . "/" . 1 x $2 ) =~ m{
                ^
                (?|    1+      / (1)  # trivial case: GCD=1
                  |  (11+) \1* / \1+  # find the GCD
                )
                 $
            }x
        })
          # more portable version of (*PASS)
     | ^  # more portable version of (*FAIL)
     )
}x;

You can improve maintainability by splitting out the version that matches the unary version from the one that matches the decimal version like this:

# this one assumes unary notation
my $unary_rx = qr{
    ^ 
    (?|   1+       / (1)
      | (11+)  \1* / \1+ 
    ) 
    $
}x;

# this one assumes decimal notation and converts internally
my $decimal_rx = qr{
  # first match a fraction:
    ^ ( \d+ ) / ( \d+ ) $ 
  # now for the hard part:
    (?(?{( 1 x $1 . "/" . 1 x $2 ) =~ $unary_rx})
          # more portable version of (*PASS)
     | ^  # more portable version of (*FAIL) 
     )
}x;

Isn’t that much easier by separating it into two named regexes? That would now make $reducible_rx the same as $decimal_rx, but the unary version is its own thing. That’s how I would do it, but the original poster wanted a single regex, so you’d have to interpolate the nested one for that as I first present above.

Either way, you can plug into the test harness below using:

    if ($frac =~ $reducible_rx) {
        cmp_ok($frac, "ne", reduce($i, $j), "$i/$j is $test");
    } else {
        cmp_ok($frac, "eq", reduce($i, $j), "$i/$j is $test");
    }

And you will see that it is a correct regex that passes all tests, and does so moreover using a single regex, wherefore having now passed all requirements of the original question, I declare Qᴜᴏᴅ ᴇʀᴀᴛ ᴅᴇᴍᴏɴsᴛʀᴀɴᴅᴜᴍ: "Quit, enough done."

这篇关于正则表达式来匹配不可分的分数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆