测试字符串是否在括号内保持平衡


15

我们将parens组称为open paren (,与其匹配的close paren )以及其中的所有内容。

如果parens组或字符串不包含任何内容或仅包含2个括号平衡的parens组,则称为括号平衡

例如:

The string   "(()())()"      is parenthesly balanced
              (    )()       Because it contains exactly 2 parenthesly balanced parens groups
               ()()          The left one is parenthesly balanced because it contains 2 parenthesly balanced parens groups (balanced because they are empty). The right one is parenthesly balanced because it contains nothing.

同样地:

The string   "(()(()))()"    is not parenthesly balanced
              (      )()     Because it contains a parens group that is not parenthesly balanced: the left one
               ()(  )        The left one is not balanced because it contains a parens group that is not balanced: the right one
                  ()         The right one is not balanced because it only contains one balanced group.

因此,带括号的字符串或括号组应该:

  • 完全不包含任何内容。
  • 或仅包含正好两个括号内的平衡括号组。它不应包含任何其他内容。

任务:

您的任务是编写一个函数或程序,以检查给定的字符串是否是括号内平衡的字符串。

输入:

输入将是字符串或字符列表或类似内容。您可以假设该字符串仅由字符'('和组成')'。您还可以假设每个打开的paren (都有其匹配的关闭paren ),因此不必担心像"((("or ")("或or 这样的字符串"(())("

注意:正如@DigitalTrauma在其评论栏中提到的,可以()用其他字符代替组合(例如<>[]...),如果它造成额外的工作就像在一些语言逃逸

输出:

表示字符串是否在括号内平衡的任何信息(对或错,1或0,...)。请在您的答案中包括您希望函数/程序产生的结果。

例子:

""                                        => True
"()()"                                    => True
"()(()())"                                => True
"(()(()(()())))(()())"                    => True
"(((((((()())())())())())())())()"        => True
"()"                                      => False
"()()()"                                  => False
"(())()"                                  => False
"()(()(())())"                            => False
"(()())(((((()())()))())())"              => False
"()(()()()())"                            => False
"()(()(()())()())"                        => False

最后两个示例确实有所作为!

祝你好运!


是否有任何信号表明字符串是否在括号内平衡?是否需要一致的输出,即仅两个值?
路易斯·门多

@LuisMendo可以是类别。即,真实值表示真实性,虚假值表示其他。因此,可能还有更多,但仍应保持一致。
易卜拉欣·莫里尔

1
如果我将二进制列表作为输入可以吗?例如,"(()())()"将表示为[0, 0, 1, 0, 1, 1, 0, 1]。这将消除将输入转换为字符代码然后相减的必要性。
JungHwan Min '18


1
@WindmillCookies我不知道这和这个有什么关系。完全不同的事情。即使是概念也不同。
易卜拉欣·莫里尔

Answers:


8

Japt v2,20个字节

V="()"V¥iU1 eViV²1 V

在线测试!

最初,每个人都误解了挑战,尽管每对括号必须包含偶数个子对,但实际上挑战实际上要求0或2个子对。因此,这是我的修改后答案,使用与以前相同的技术。

我们仍然可以通过递归替换解决挑战。问题是,不仅仅是删除所有出现的()(),我们还需要确保在同一包装中除了之外没有其他东西()()(换句话说,没有()()()()或类似的东西)。我们可以通过用递归替换(()())来实现()

新的问题是输入本身没有一对外部括号(因为这将使其不成为括号内的平衡字符串),迫使我们将其包装在额外的一对中以完全减少它。最后,平衡字符串的最终结果现在()不是空字符串,因此我们检查是否相等,而不仅仅是对输出进行逻辑非。


7

sed 4.2.2、30

:
s/(()())/()/
t
/^()()$\|^$/q1

在线尝试

这将返回shell退出代码,其中True表示1,False表示0。

:               # label
s/(()())/()/    # replace "(()())" with "()"
t               # jump back to label if above replacement matched
/^()()$\|^$/q1  # exit code 1 if remaining buffer is exactly "()()" or empty
                # otherwise exit with code 0

7

Perl 5 -lp,24 22字节

$_=/^((<(?1)?>){2})?$/

在线尝试!链接包括测试用例。编辑:由于@JoKing,节省了2个字节。说明:只是一个递归正则表达式。外部捕获组表示一个平衡字符串,<后跟一个可选的平衡字符串,后跟一个>。请注意,大多数其他答案都可以使用()s,但这会额外花费两个字节:

$_=/^((\((?1)?\)){2})?$/

在线尝试!链接包括测试用例。


3
由于您可以使用其他成对的括号,因此可以使用<>
Jo King

1
@JoKing几乎所有其他答案都可以使用()s,所以我认为这不是一个公平的比较,但是我看到@ngn的APL答案也使用<>s,所以我更新了这个。
尼尔,

6

6502机器代码例程,48个字节

A0 00 84 FD A2 00 B1 FB F0 0E C8 C9 29 18 F0 06 8A 48 E6 FD 90 EE B0 0A E0 01
90 06 E0 02 38 D0 01 18 A5 FD F0 09 C6 FD 68 AA E8 B0 F5 90 D7 60

需要一个指向$fb/ $fc中的字符串的指针,该字符串仅包含()。如果字符串“是平衡的”,则清除C(传送)标志,否则进行设置(这是6502上的典型用法,设置进位“错误”)。对无效输入不做任何明智的选择。

尽管该算法是递归的,但它不会自行调用(这将需要更多的字节依赖于代码位置),而是自己维护递归深度并使用“简单”分支。

评论拆解

; function to determine a string is "paranthesly balanced"
;
; input:
;   $fb/$fc: address of the string
; output:
;   C flag set if not balanced
; clobbers:
;   $fd:     recursion depth
;   A,X,Y

 .isparbal:
A0 00       LDY #$00            ; string index
84 FD       STY $FD             ; and recursion depth
 .isparbal_r:
A2 00       LDX #$00            ; set counter for parantheses pairs
 .next:
B1 FB       LDA ($FB),Y         ; load next character
F0 0E       BEQ .done           ; end of string -> to final checks
C8          INY                 ; increment string index
C9 29       CMP #$29            ; compare with ')'
18          CLC                 ; and reset carry
F0 06       BEQ .cont           ; if ')' do checks and unwind stack
8A          TXA                 ; save counter ...
48          PHA                 ; ... on stack
E6 FD       INC $FD             ; increment recursion depth
90 EE       BCC .isparbal_r     ; and recurse
 .cont:
B0 0A       BCS .unwind         ; on previous error, unwind directly
 .done:
E0 01       CPX #$01            ; less than one parantheses pair
90 06       BCC .unwind         ; -> ok and unwind
E0 02       CPX #$02            ; test for 2 parantheses pairs
38          SEC                 ; set error flag
D0 01       BNE .unwind         ; if not 2 -> is error and unwind
18          CLC                 ; clear error flag
 .unwind:
A5 FD       LDA $FD             ; check recursion depth
F0 09       BEQ .exit           ; 0 -> we're done
C6 FD       DEC $FD             ; otherwise decrement
68          PLA                 ; get "pair counter" ...
AA          TAX                 ; ... from stack
E8          INX                 ; and increment
B0 F5       BCS .unwind         ; continue unwinding on error
90 D7       BCC .next           ; otherwise continue reading string
 .exit:
60          RTS

使用例程的示例C64汇编程序:

在线演示

screenshot

ca65语法中的代码:

.import isparbal   ; link with routine above

.segment "BHDR" ; BASIC header
                .word   $0801           ; load address
                .word   $080b           ; pointer next BASIC line
                .word   2018            ; line number
                .byte   $9e             ; BASIC token "SYS"
                .byte   "2061",$0,$0,$0 ; 2061 ($080d) and terminating 0 bytes

.bss
linebuf:        .res    256

.data
prompt:         .byte   "> ", $0
truestr:        .byte   "true", $0
falsestr:       .byte   "false", $0

.code
inputloop:
                lda     #<prompt        ; display prompt
                ldy     #>prompt
                jsr     $ab1e

                lda     #<linebuf       ; read string into buffer
                ldy     #>linebuf
                ldx     #0              ; effectively 256
                jsr     readline

                lda     #<linebuf       ; address of string to $fb/fc
                sta     $fb
                lda     #>linebuf
                sta     $fc
                jsr     isparbal        ; call function

                bcs     isfalse
                lda     #<truestr
                ldy     #>truestr
                bne     printresult
isfalse:        lda     #<falsestr
                ldy     #>falsestr
printresult:    jmp     $ab1e           ; output true/false and exit

; read a line of input from keyboard, terminate it with 0
; expects pointer to input buffer in A/Y, buffer length in X
.proc readline
                dex
                stx     $fb
                sta     $fc
                sty     $fd
                ldy     #$0
                sty     $cc             ; enable cursor blinking
                sty     $fe             ; temporary for loop variable
getkey:         jsr     $f142           ; get character from keyboard
                beq     getkey
                sta     $2              ; save to temporary
                and     #$7f
                cmp     #$20            ; check for control character
                bcs     checkout        ; no -> check buffer size
                cmp     #$d             ; was it enter/return?
                beq     prepout         ; -> normal flow
                cmp     #$14            ; was it backspace/delete?
                bne     getkey          ; if not, get next char
                lda     $fe             ; check current index
                beq     getkey          ; zero -> backspace not possible
                bne     prepout         ; skip checking buffer size for bs
checkout:       lda     $fe             ; buffer index
                cmp     $fb             ; check against buffer size
                beq     getkey          ; if it would overflow, loop again
prepout:        sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
output:         lda     $2              ; load character
                jsr     $e716           ;   and output
                ldx     $cf             ; check cursor phase
                beq     store           ; invisible -> to store
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and show
                ora     #$80            ;   cursor in
                sta     ($d1),y         ;   current row
                lda     $2              ; load character
store:          cli                     ; enable interrupts
                cmp     #$14            ; was it backspace/delete?
                beq     backspace       ; to backspace handling code
                cmp     #$d             ; was it enter/return?
                beq     done            ; then we're done.
                ldy     $fe             ; load buffer index
                sta     ($fc),y         ; store character in buffer
                iny                     ; advance buffer index
                sty     $fe
                bne     getkey          ; not zero -> ok
done:           lda     #$0             ; terminate string in buffer with zero
                ldy     $fe             ; get buffer index
                sta     ($fc),y         ; store terminator in buffer
                sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
                inc     $cc             ; disable cursor blinking
                cli                     ; enable interrupts
                rts                     ; return
backspace:      dec     $fe             ; decrement buffer index
                bcs     getkey          ; and get next key
.endproc

5

V21,20字节

é(Á)òÓ(“()()…)òø^()$

在线尝试!验证所有测试用例!

é(                      " Insert '(' at the beginning of the line
  Á)                    " Append ')' at the end
    ò         ò         " Recursively...
     Ó                  "   Remove...
      (                 "     '('
       “    …           "     (Limit the part that is removed to this section of the match)
        ()()            "     '()()'
             )          "     ')'
                        " (effectively, this replaces '(()())' with '()', but it's one byte shorter than the straightforward approach
               ø        " Count...
                ^()$    "   Lines containing exactly '()' and nothing more

十六进制转储:

00000000: e928 c129 f2d3 2893 2829 2829 8529 f2f8  .(.)..(.()().)..
00000010: 5e28 2924                                ^()$

您能否解释一下代码,以便(希望)找到一个无效的测试用例,就像我对@Adàm的答案所做的那样
易卜拉欣·莫里尔

@ibrahimmahrir完成。
DJMcMayhem

5

Brachylog,28个字节

Ẹ|~c["(",A,")(",B,")"]∧A;B↰ᵐ

在线尝试!

说明

                                    --  The string perfectly balanced iff
Ẹ                                   --      the string is empty
 |                                  --  or
  ~c["(",A,")(",B,")"]              --      the string can be written id the format of "($A)($B)"
                      ∧             --          where
                       A;B ᵐ        --          both A and B
                          ↰         --          are perfectly balanced

4

C(gcc),113个字节

p(a,r,e,n)char*a;{if(*a-40)return 1;for(r=1,e=0;e<2;r&=e++||*a==40)for(r*=n=p(++a);n+=*a++-40?~0:1;);r=r&&*a-40;}

在线尝试!

说明

p(a,r,e,n)char*a;{   // function and variable declaration
 if(*a-40)return 1;  // string does not start with '(', thus is empty
 for(r=1,e=0;e<2;    // r: return value, e: group id (look for exactly two groups)
 r&=e++||*a==40)     // after the first group, a second shall follow
  for(r*=n=p(++a);   // check that the group is itself balanced
  n+=*a++-40?~0:1;); // skip group
 r=r&&*a-40;}        // additionally, after those two groups there shall follow none

在线尝试!


3

MATL26 25字节

oo~`tnw52B5LZttnb<]XB10X-

在线尝试!

感谢@ETHProductions回答“用()替换(()())”的想法,以及@JungHwan Min提出的将括号视为二进制数字的想法的问题注释。

输出是一个空数组,表示真值,一个正数表示假-我认为OP的注释允许这样做:“可以是类别。即,真值表示真实性,假值表示否。” 如果不是,我们可以n在末尾添加+1个字节,以将0作为真实输出,将1作为虚假输出。

有评论:

o         % Convert the parantheses to their ASCII codes
          %  40 for '(', 41 for ')'
o         % Parity - 1 for odd, 0 for even
~         % Not - change 0 to 1 and vice versa, so '(' is now 1 and ')' 0
          % Input char array is now a binary array B
`         % Do-while loop
  tn          % Get the length of the array 
  w           % Bring the array B back on top
  52B         % Push the binary value of 52 on stack
              %  [1 1 0 1 0 0] (equivalent to '(()())')
  5L          % Push the constant [1 0] for '()'
  Zt          % Replace the sequence [1 1 0 1 0 0] in array B
              %  with [1 0]
  tn          % Get the length of the array after replacement 
  b<          % Has it decreased? If so, continue loop
  ]       % end loop
          % Final value for balanced input will be
          %  either [1 0 1 0] for the remaining outer '()()'
          %  or an empty array [] for empty '' input
XB        % Convert the final binary array back to decimal
10X-      % Set difference, remove 10 from that result 
          % Result is [] empty array for balanced input, otherwise 
          %  some decimal number ≠ 10 for unbalanced input


3

Haskell82 59字节

all(`elem`[0,2]).foldl(#)[0]
b#'('=0:b
(x:y:z)#_=y+1:z++[x]

在线尝试!

我想它可以打得更远,因为这是我第一次在Haskell打高尔夫球,所以任何花招或评论都值得欢迎。

编辑-感谢@nimi保存了23个字节(超过原始提交内容的28%:)


1
一些提示:不需要()周围y+1。由于允许使用未命名的函数,因此可以删除f=,这r[0]是一个适当的函数。将基本案例r b[]放在最后并切换到infix函数(例如#),然后可以使用b#_=。您也可以通过逐步构建列表来逐步检查0s和2s 来稍微更改算法,而不是将其随基本情况r累加到累加器的调用中。首次通话后进行检查。总共73个字节。r(x:y:z) ... = x : r (...) ar b [] = br[0]
nimi


1
...甚至更好:与累加器呆在一起并切换至foldl(59字节):在线尝试!
nimi

@nimi非常感谢,正是我一直在寻找的技巧:)
Vincent

3

JavaScript(ES6),63个字节

将输入作为字符数组。返回的parenthesly平衡,不parenthesly平衡。

a=>[...a,k=0].some(c=>c<')'?!(a[k]=-~a[k++]):a[k]=~5>>a[k--]&1)

在线尝试!

已评论

a =>                     // a[] = input array of characters; we are going to reuse it to
  [                      // store the number of parenthesis groups at each depth
    ...a,                // append all characters
    k = 0                // initialize k = current depth to 0 and append a value that will
  ]                      // be treated as a final closing parenthesis for the root level
  .some(c =>             // for each character c in this array:
    c < ')' ?            //   if c is an opening parenthesis:
      !(                 //     increment the number of groups at the current depth
        a[k] = -~a[k++]  //     increment the depth
      )                  //     yield false
    :                    //   else:
      a[k] = ~5          //     make sure that the current depth contains either 0 or 2
             >> a[k--]   //     groups, by shifting the 1-complement of 5 (101 in binary)
             & 1         //     and testing the least significant bit
                         //     it resets the number of groups to 0 if the bit is not set
                         //     otherwise, it forces some() to return true
                         //     decrement the depth
  )                      // end of some()

递归,54个字节

但是,使用递归替换(例如在ETHproductions的Japt答案中)大大缩短了。

将输入作为字符串。对于圆括号平衡返回1,对于非圆括号平衡返回0

f=s=>s==(s=s.split`(()())`.join`()`)?!s|s=='()()':f(s)

在线尝试!


递归,46字节

由于括号不平衡,这引发了递归错误:

f=s=>!s|s=='()()'||f(s.split`(()())`.join`()`)

在线尝试!


我的JavaScript不好,但是可以用x [k] ++; k ++甚至++ x [k ++]代替x [k] =-〜x [k ++]吗?
АндрейЛомакин

2
@АндрейЛомакин不,因为x[k]最初未定义,所以x[k]++会给出NaN,而-~undefined给出1
阿纳尔德

@АндрейЛомакин我现在正在重新使用输入数组,因此a[k]最初包含一个字符。但是,同样的逻辑也适用于字符串:将++运算符应用于它们产生yield NaN,但是按位运算符(例如~)会强制将它们强制转换为0事先强制执行。
Arnauld

将javascript提升到一个全新的水平。:D
易卜拉欣·莫里尔

3

Perl 6的 43 41  37个字节

{my rule f{\([<&f>**2]?\)};?/^<&f>**2$|^$/}

测试一下

{(my$f)=/\([<$f>**2]?\)/;?/^[<$f>**2]?$/}

测试一下

{$!=/\([<$!>**2]?\)/;?/^[<$!>**2]?$/}

测试一下

展开:

{  # bare block lambda with implicit parameter $_

  $! = # store regex into $! (no need to declare it)
  /
    \(

      [
        <$!> ** 2 # recurse into regex twice
      ]?          # optionally

    \)
  /;


  ?      # boolify (causes it to be run against $_)

    /
      ^         # beginning of string

      <$!> ** 2 # match using regex twice

      $         # end of string

    |           # or

      ^ $       # empty string
    /
}

3

R,71个字节

f=function(s,r=sub('(()())','()',s,f=T))'if'(r==s,s==''|s=='()()',f(r))

在线尝试!

  • @ETHproductions的递归Japt解决方案的移植
  • -2个字节,感谢@JayCe

另一个较长的解决方案,但对于不同的方法很有趣

R,85字节

g=gsub;!sum(eval(parse(t=g('\\)\\(',')-(',g('\\)','-1)',g('\\(','(2+',scan(,'')))))))

在线尝试!

说明:

接受输入字符串并替换:

'('  with '(2+'
')'  with '-1)'
')(' with ')-('

然后评估结果表达式。如果等于零则平衡,否则不平衡。sum仅在处理空字符串的情况下才需要使用,因为它的评估返回NULL

例如

()(()()) => (2+-1)-(2+(2+-1)-(2+-1)-1) = 0
(()())   => (2+(2+-1)-(2+-1)-1)        = 1

保存两个字节:f=function(s,r=sub('(()())','()',s,f=T))'if'(r==s,s==''|s=='()()',f(r))
JayCe

您应该把较短的解决方案放在首位
纯ASCII码

仅限
@ASCII

3
@digEmAll那么,在很多的挑战,这里大多数的挑战只是端口另一种解决方案
ASCII-仅


2

05AB1E18 16 13 字节

…(ÿ)…(()∞„()©:®Q

@ETHproductions的Japt答案端口用于修复测试用例()(()()(()())(()()))
-2个字节,感谢@Adnan

基于OP的注释,我现在将其()用作真实值,并将其他任何值用作虚假值。如果两个值都需要一致而不是一个,那么它将是旧的16字节答案(…(ÿ)…(()∞„()©:®Q),返回0真值,1假测试用例。

在线尝试验证所有测试用例

说明

…(ÿ)             # Take the input (implicitly) and surround it with "(" and ")"
            :    # Infinite replacement of:
    …(()∞        #  "(()())"    ("(()" mirrored)
         „()     #  with "()"
                 # After the infinite replacement: return the result
                 # ("()" for truthy; falsey otherwise)

(旧的18字节答案在测试用例中失败了()(()()(()())(()()))..):

ΔD„()∞©6∍å_i®õ.:]Ā

在线尝试验证所有测试用例


我认为您可以使用无限替换方法:„()∞õ:g_
阿德南(Adnan)'18

等等,我误解了挑战
Adnan

@Adnan我也一开始也这么认为,但对于包含(()()()())应该返回false的测试用例,它失败了。每个括号组应恰好包含0或2个内部组。
凯文·克鲁伊森

1
您可以替换'(®')J…(ÿ)
阿德南(Adnan)'18

@Adnan谢谢!我知道ÿ存在,但以前从未使用过,所以完全忘记了它。
凯文·克鲁伊森




1

Brainfuck,50个字节

,[<+>[-[->>]<[-[--[>->,]]>>]<]<[>>],]<[--[>->]]<+.

格式:

,
[
  <+>
  [
    -[->>]
    <
    [
      -
      [
        --
        [
          >->,
        ]
      ]
      >>
    ]
    <
  ]
  <[>>]
  ,
]
<
[
  --
  [
    >->
  ]
]
<+.

期望包含()不包含尾随换行符的字符串,并输出\x01true和\x00false。(为便于清晰,你可以如增加48个+最终S前.,使其打印10代替。)

在线尝试

这样可以维护一个堆栈,该堆栈具有每个深度处的组数,并通过奇偶校验来区分字符,并在每次闭合括号后检查组数是否在{0,2}中;如果不满足条件,则消耗其余的输入并设置一个标志;然后在程序结束时再次检查条件。

如果允许我们使用奇数字符终止输入流,则可以省略最后的检查<[--[>->]]以节省10个字节。(如果\n不是很不方便,我可能会建议使用此变体作为主要答案。)

(我们还可以通过将输出格式更改为 \x00为true和non- \x00for false,这似乎是书面问题语句允许的(可能是偶然的),但是无论如何这不是很有趣,我更喜欢不要做出改变。)


1

Python2,95 94个字节

f=lambda i:g(eval("(%s)"%i.replace(")","),")))
g=lambda i:len(i)in(0,2)and all(g(j)for j in i)

在线尝试!

f()将字符串转换为嵌套元组,然后将其传递给g()。

g()递归地导航该元组,如果任何元素不完全具有0或2个子元素,则返回False。

使用字符串格式保存一个字节。


1

Stax13 11 字节

₧aaS▐îî»Å·╢

运行并调试

当我意识到输入可以同时隐式地评估为数组文字时,我节省了两个字节。通过删除双引号,可以简化输入。

通常的想法是将输入评估为数组文字,然后递归映射元素以检查是否平衡。如果最终断言失败,那么随后在空堆栈上将弹出。在stax中,用空堆栈弹出会立即终止程序。

拆开包装,松开包装并进行评论,看起来像这样。

        input is implicitly treated as array literals
L       wrap entire input stack in an array
G       jump to the trailing '}', and come back when done
}       terminate the program, the rest is a recursive call target
{Gm     map array on top of the stack by using the recursive call target
%       get the length of the mapped array
02\#    is the length one of [0, 2]?
|c      assert value is truthy, pop if not

运行这个


1

Java 10、99 96 95 83字节

s->{s="("+s+")";for(var p="";!p.equals(s);s=s.replace("(()())","()"))p=s;return s;}

我的05AB1E答案的端口(所以也返回()真实值,其他虚假值)。

在线尝试。

说明:

s->{                 // Method with String as both parameter and return-type
  s="("+s+")";       //  Surround the input-String between "(" and ")"
  for(var p="";      //  Previous-String, starting empty
      !p.equals(s)   //  Loop as long as the previous and current Strings differ
      ;              //    After every iteration:
       s=s.replace("(()())","()"))
                     //     Replace all "(()())" with "()"
    p=s;             //   Set the previous String with the current
  return s;}         //  Return the modified input-String
                     //  (if it's now "()" it's truthy; falsey otherwise)

return s;可能是return"()".equals(s);是否需要实际的布尔结果。


如果您仅检查一下就可以节省一个字节!s.contains("()()(")
Charlie

@Charlie谢谢,但是代码仍然包含一个错误,因此必须对其进行更改。现在已修复(针对最后添加的false测试用例),并同时进行了4个字节的修改。
凯文·克鲁伊森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.