Масштабируемый Regex для английских цифр

Вот решение в Python на основе программирования с использованием ограничительного языка:

from constraint import AllDifferentConstraint, InSetConstraint, Problem

# variables
colors        = "blue red green white yellow".split()
nationalities = "Norwegian German Dane Swede English".split()
pets          = "birds dog cats horse zebra".split()
drinks        = "tea coffee milk beer water".split()
cigarettes    = "Blend, Prince, Blue Master, Dunhill, Pall Mall".split(", ")

# There are five houses.
minn, maxn = 1, 5
problem = Problem()
# value of a variable is the number of a house with corresponding property
variables = colors + nationalities + pets + drinks + cigarettes
problem.addVariables(variables, range(minn, maxn+1))

# Each house has its own unique color.
# All house owners are of different nationalities.
# They all have different pets.
# They all drink different drinks.
# They all smoke different cigarettes.
for vars_ in (colors, nationalities, pets, drinks, cigarettes):
    problem.addConstraint(AllDifferentConstraint(), vars_)

# In the middle house they drink milk.
#NOTE: interpret "middle" in a numerical sense (not geometrical)
problem.addConstraint(InSetConstraint([(minn + maxn) // 2]), ["milk"])
# The Norwegian lives in the first house.
#NOTE: interpret "the first" as a house number
problem.addConstraint(InSetConstraint([minn]), ["Norwegian"])
# The green house is on the left side of the white house.
#XXX: what is "the left side"? (linear, circular, two sides, 2D house arrangment)
#NOTE: interpret it as 'green house number' + 1 == 'white house number'
problem.addConstraint(lambda a,b: a+1 == b, ["green", "white"])

def add_constraints(constraint, statements, variables=variables, problem=problem):
    for stmt in (line for line in statements if line.strip()):
        problem.addConstraint(constraint, [v for v in variables if v in stmt])

and_statements = """
They drink coffee in the green house.
The man who smokes Pall Mall has birds.
The English man lives in the red house.
The Dane drinks tea.
In the yellow house they smoke Dunhill.
The man who smokes Blue Master drinks beer.
The German smokes Prince.
The Swede has a dog.
""".split("\n")
add_constraints(lambda a,b: a == b, and_statements)

nextto_statements = """
The man who smokes Blend lives in the house next to the house with cats.
In the house next to the house where they have a horse, they smoke Dunhill.
The Norwegian lives next to the blue house.
They drink water in the house next to the house where they smoke Blend.
""".split("\n")
#XXX: what is "next to"? (linear, circular, two sides, 2D house arrangment)
add_constraints(lambda a,b: abs(a - b) == 1, nextto_statements)

def solve(variables=variables, problem=problem):
    from itertools  import groupby
    from operator   import itemgetter

    # find & print solutions
    for solution in problem.getSolutionIter():
        for key, group in groupby(sorted(solution.iteritems(), key=itemgetter(1)), key=itemgetter(1)):
            print key, 
            for v in sorted(dict(group).keys(), key=variables.index):
                print v.ljust(9),
            print

if __name__ == '__main__':
    solve()

Вывод:

1 yellow    Norwegian cats      water     Dunhill  
2 blue      Dane      horse     tea       Blend    
3 red       English   birds     milk      Pall Mall
4 green     German    zebra     coffee    Prince   
5 white     Swede     dog       beer      Blue Master

требуется 0,6 секунды (ЦП 1.5 ГГц) для нахождения решения.
ответ является "немецким языком, владеет зеброй".

Для установки constraint модуль через pip: победите ограничение Python установки

Для установки вручную:

5
задан João Silva 15 August 2009 в 17:56
поделиться

4 ответа

См. Perl Lingua :: EN :: Words2Nums и Lingua :: EN :: FindNumber . ​​

В частности, исходный код для Lingua :: EN :: FindNumber содержит:

# This is from Lingua::EN::Words2Nums, after being thrown through
# Regex::PreSuf
my $numbers =
    qr/((?:b(?:akers?dozen|illi(?:ard|on))|centillion|d(?:ecilli(?:ard|on)|ozen|u(?:o(?:decilli(?:ard|on)|vigintillion)|vigintillion))|e(?:ight(?:een|ieth|[yh])?|leven(?:ty(?:first|one))?|s)|f(?:i(?:ft(?:een|ieth|[yh])|rst|ve)|o(?:rt(?:ieth|y)|ur(?:t(?:ieth|[yh]))?))|g(?:oogol(?:plex)?|ross)|hundred|mi(?:l(?:ion|li(?:ard|on))|nus)|n(?:aught|egative|in(?:et(?:ieth|y)|t(?:een|[yh])|e)|o(?:nilli(?:ard|on)|ught|vem(?:dec|vigint)illion))|o(?:ct(?:illi(?:ard|on)|o(?:dec|vigint)illion)|ne)|qu(?:a(?:drilli(?:ard|on)|ttuor(?:decilli(?:ard|on)|vigintillion))|in(?:decilli(?:ard|on)|tilli(?:ard|on)|vigintillion))|s(?:core|e(?:cond|pt(?:en(?:dec|vigint)illion|illi(?:ard|on))|ven(?:t(?:ieth|y))?|x(?:decillion|tilli(?:ard|on)|vigintillion))|ix(?:t(?:ieth|y))?)|t(?:ee?n|h(?:ir(?:t(?:een|ieth|y)|d)|ousand|ree)|r(?:e(?:decilli(?:ard|on)|vigintillion)|i(?:gintillion|lli(?:ard|on)))|w(?:e(?:l(?:fth|ve)|nt(?:ieth|y))|o)|h)|un(?:decilli(?:ard|on)|vigintillion)|vigintillion|zero|s))/i;

в соответствии с художественной лицензией Perl .

Вы можете использовать Regex :: PreSuf для автоматически вычеркивает общие пре- и суффиксы:

#!/usr/bin/perl

use strict;
use warnings;

use Regex::PreSuf;

my %singledigit = (
    one    => 1,
    two    => 2,
    three  => 3,
    four   => 4,
    five   => 5,
    six    => 6,
    seven  => 7,
    eight  => 8,
    nine   => 9,
);

my $singledigit = presuf(keys %singledigit);

print $singledigit, "\n";

my $text = "one two three four five six seven eight nine";

$text =~ s/($singledigit)/$singledigit{$1}/g;

print $text, "\n";

Вывод:

C:\Temp> cvb
(?:eight|f(?:ive|our)|nine|one|s(?:even|ix)|t(?:hree|wo))
1 2 3 4 5 6 7 8 9

Боюсь, после этого станет труднее; -)

8
ответ дан 13 December 2019 в 19:32
поделиться

Создайте сценарий bash с именем client.sh:

#!/bin/bash

cat someFile

while read FOO; do
        echo $FOO >&3
        if [[ $FOO =~ `printf ".*\x00\x1c.*"` ]]; then
                break
        fi
done

. Затем вызовите netcat из основного сценария следующим образом:

3>&1 nc -c ./client.sh somehost 1234

(Для сопоставления регулярных выражений вам понадобится версия 3 bash).

Предполагается, что сервер отправляет данные по строкам - в противном случае вам придется настроить client.sh так, чтобы он считывал и отображал символ за раз.

Вы можете увидеть примеры вывода Regexp :: Assemble, Regexp :: List, Regexp :: Optimizer и Regex :: PreSuf в http://groups.google.com/group/perl.perl5.porters/msg/ 132877aee7542015 . Начиная с perl 5.10, perl сам обычно оптимизирует списки | d точных строк в дерево.

3
ответ дан 13 December 2019 в 19:32
поделиться

Что вы пытаетесь сделать и какой алгоритм вы используете?

Я не знаком с механизмом регулярных выражений Java, но с другими механизмами регулярных выражений, которые я использовал (Perl, awk) позволяют снимать матчи. Например, если вы пытаетесь сопоставить:

один миллион сто тысяч сто один

У вас может быть регулярное выражение, которое может идентифицировать миллион, все, что перед ним (например, «один»), и все, что после него (т.е. «сто тысяч сто один»). То, что было раньше, будет захвачено для дополнительного сопоставления (с использованием ваших регулярных выражений сотен, десятков и единиц), а вещи после него будут захвачены для дополнительного сопоставления (с использованием вашего регулярного выражения тысяч, сотен регулярных выражений, десятков регулярных выражений или регулярных выражений единиц).

Этот алгоритм естественно рекурсивен, и его несложно реализовать.

0
ответ дан 13 December 2019 в 19:32
поделиться

Regex действительно плохой способ сделать это. Лично я просто создал бы небольшую карту всех известных слов и стал бы искать таким образом. (Найдите каждое слово, когда вы найдете совпадение, определите, совпадают ли слова рядом с ним, и продолжайте так, пока не получите номер).

0
ответ дан 13 December 2019 в 19:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: