首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于CharMatcher.WHITESPACE实现

关于CharMatcher.WHITESPACE实现
EN

Stack Overflow用户
提问于 2014-02-10 04:07:36
回答 1查看 217关注 0票数 0

当我查找CharMatcher的实现并注意到一个字段WHITESPACE_MULTIPLIER=1682554634时,我将这个值设置为1582554634,运行testcase CharMatcherTest#testWhitespaceBreakingWhitespaceSubset,当然它失败了。

之后,我将testWhitespaceBreakingWhitespaceSubset更改为只调用没有断言的WHITESPACE.apply((char)c),然后在WHITESPACE.matches方法中打印索引。

代码语言:javascript
复制
int index=(WHITESPACE_MULTIPLIER * c) >>> WHITESPACE_SHIFT)

最后发现,在将WHITESPACE_MULTIPLIER1682554634改为1582554634后,索引发生了冲突。

毫无疑问,1682554634设计得很好,我的问题是如何推断出这个“魔术数字”?

Martin的建议上,我尝试编写“魔术数字生成器”,如下所示并工作:

代码语言:javascript
复制
char[] charsReq = WHITESPACE_TABLE.toCharArray();
Arrays.sort(charsReq);
OUTER:
for (int WHITESPACE_MULTIPLIER_WANTTED = 1682553701; WHITESPACE_MULTIPLIER_WANTTED <= 1682554834; WHITESPACE_MULTIPLIER_WANTTED++) {
    int matchCnt = 0;
    for (int c = 0; c <= Character.MAX_VALUE; c++) {
        int position = Arrays.binarySearch(charsReq, (char) c);
        char index = WHITESPACE_TABLE.charAt((WHITESPACE_MULTIPLIER_WANTTED * c) >>> WHITESPACE_SHIFT);
        if (position >= 0 && index == c) {
                matchCnt++;
        } else if (position < 0 && index != c) {
                matchCnt++;
        } else {
            continue OUTER;
        }
    }
    // all valid
    if ((matchCnt - 1) == (int) (Character.MAX_VALUE)) {
        System.out.println(WHITESPACE_MULTIPLIER_WANTTED);
    }
}

如果更改WHITESPACE_TABLE中的字符序列(swap \u2001 \u2002位置),则算法没有解决方案(将循环结束条件更改为Integer.MAX_VALUE)。

由于IntMath.gcd实现是指算法

我的问题是:在哪里可以找到CharMatcher.WHITESPACE.match实现的材料?

EN

回答 1

Stack Overflow用户

发布于 2014-02-10 04:36:15

我不确定生成器是否还存在于某个地方,但它可以很容易地重新创建。类Result包含在CharMatcher.WHITESPACE中使用的数据。

代码语言:javascript
复制
static class Result {
    private int shift;
    private int multiplier;
    private String table;
}

// No duplicates allowed.
private final String allMatchingString = "\u2002\r\u0085\u200A\u2005\u2000"
        + "\u2029\u000B\u2008\u2003\u205F\u1680"
        + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
        + "\u2004\u2028\n\u2007\u3000";

public Result generate(String allMatchingString) {
    final char[] allMatching = allMatchingString.toCharArray();
    final char filler = allMatching[allMatching.length - 1];
    final int shift = Integer.numberOfLeadingZeros(allMatching.length);
    final char[] table = new char[1 << (32 - shift)];
    OUTER: for (int i=0; i>=0; ++i) {
        final int multiplier = 123456789 * i; // Jumping a bit makes the search faster.
        Arrays.fill(table, filler);
        for (final char c : allMatching) {
            final int index = (multiplier * c) >>> shift;
            if (table[index] != filler) continue OUTER; // Conflict found.
            table[index] = c;
        }
        return new Result(shift, multiplier, new String(table));
    }
    return null; // No solution exists.
}

它产生了不同的乘数,但这并不重要。

如果没有给定allMatchingString的解决方案,则可以减少移位,然后再试一次。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21668919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档