オートバイのギアチェッカー!


36

あなたの何人かは、オートバイがシフトする方法に精通しているかもしれません。しかし、そうでない人のために、それはこのように見えます

6

5

4

3

2

N

1

今、私はいくつかのアップシフトとダウンシフトを行った後、私がどんなギアにいるのか知りたいです。プログラムは中立から動作するはずです。

サンプル入力:

V^^

サンプル出力:

2

ご覧のとおり、私はNから1に1回ダウンシフトし、2番目のギアに2回アップシフトしました。

これはコードゴルフです。バイト単位の最短回答が優先されます。

注:入力には任意の2文字を使用できます。上下のUとD、または任意の文字列にする必要があります。1速または6速を超えてシフトすることはできません。あなたが6位であり、再びアップシフトする場合、それは6位のままになります。がんばろう!


5
次回、チャレンジをサンドボックスに投稿してフィードバックを取得してからメインに投稿して
ください。fgetnɛt

1
@seshoumaraの2つの要件は、文字列でなければならず、2文字しか入力できないことです。したがって、改行を文字として使用できます。しかし、別の理由でそれを使用する場合、私は本当に気にしません。あなたが何を考えているかを見るのは面白いでしょう。しかし、もしそうするなら、なぜそうしたのかについて簡単に説明してください。GL!
マルタインVissers

4
これは、1とNの間のハーフステップシフトを考慮していないのは残念です。2N 1 N 2 3だけでなく、2 1 N 2 3
Cort Ammon

2
私は@CortAmmonに同意します-1と2の間には単一のシフトがあります。それはニュートラルが半分のシフトです。
ジュリス

2
すべてのバイクがこのように移動するわけではありません。ほとんどのクラッチレスバイクは、N-1-2-3-4(または非常に古い車両ではN-1-2-3)にシフトします。彼らはギア5または6を持っており、ラウンドギアを使用し、それは4のIEときにギアを増やすと、それはNに折り返すようになりますしていない
phuclv

回答:


15

JavaScript(ES6)、49 48 47 46バイト

期待:

  • 1 ダウン用
  • 7 アップのために
f=([c,...s],g=2)=>c?f(s,g-c&7||g):'1N'[--g]||g

書式設定およびコメント化

f = (                   // f is a recursive function which takes:
  [c,                   // - c = next character in input string
      ...s],            // - s = remaining characters
  g = 2                 // - g = current gear, with default = neutral = 2
) =>                    //
  c ?                   // if there's still a character to process:
    f(                  //   do a recursive call with:
      s,                //     - the remaining characters
      g - c & 7 ||      //     - the updated gear if it is valid
      g                 //       or the previous gear if not
    )                   //
  :                     // else:
    '1N'[--g] ||        //   decrement g and output '1' for g = 0, 'N' for g = 1,
    g                   //   or simply the corresponding digit for other values

ギアは次のようにマッピングされます。

g MOD 8 = 0 1 2 3 4 5 6 7
          ---------------
gear    = X 1 N 2 3 4 5 6       (where 'X' is an invalid state)

これにより、現在のギアの有効性を簡単に確認できます:

(g & 7) != 0

デモ


7

05AB1E22 20バイト

Îvy<+®‚Z5‚W}6LÀ'N¸ìè

オンラインでお試しください!

説明

Î                      # push 0 (accumulator) and input
 v         }           # for each in input
  y<+                  # decrement current element and add to accumulator
     ®‚Z               # take maximum of current value and -1
        5‚W            # take minimum of current value and 5
            6L         # push the range [1 ... 6]
              À        # rotate left
               'N¸ì    # prepend the letter "N" producing the list [N, 2, 3, 4, 5, 6, 1]
                   è   # index into this list with the value produced by the loop

6

MATL、32 28 23バイト

@Luisのおかげで5バイト節約

'234561N'j!Uq[aA]&Ys0))

このソリューションは'2'、アップシフトと'0'ダウンシフトに使用します。

MATL Online試しください

説明

'234561N'   % Push the string literal to the stack
j           % Grab the input as a string
!U          % Convert the input to a numeric array based on the characters.
q           % Subtract 1 to turn '2' into 1 and '0' into -1
[aA]        % Push the array [-1 5] to the stack
&Ys         % Compute the cumulative sum using the array [-1, 5] as
            % the upper and lower limits at each point
0)          % Get the last value from the cumulative sum
)           % Use this to index into the initial string literal.
            % Implicitly display the result

@Lifeless説明付きで更新
Suever

非常に素晴らしい!文字列が1n23456や65432n1ではなく234561Nなのはなぜですか?私も欠陥を見つけました!あなたはそれが6速にシフトアップとどまるべき続けるが、それはN返す場合
マルタインVissers

1
いいね!Cumsumの制限トリックについて知らなかった
B. Mehta

1
@ B.Mehta Meも!ルイスが勧めた
Suever

1
@ B.Mehtaまた、MATLチャットルームにご参加ください。
スーバー

6

V20、15のバイト

:sil!î¬61énÀxVp

オンラインでお試しください!

入力はh(上)文字とl(下)文字の文字列です。

@nmjcmanに5バイトを節約し、私が知らなかったvim機能について教えてくれてありがとう!

入力が範囲外にならないことを想定できた場合、単純に9バイトになります。

¬61énÀxVp

しかし、残念ながらそれは許可されていません。

説明:

:sil!           " If the cursor goes out of bounds, ignore it and continue
     î          " Run the following keystrokes as V code, rather than vimscript:
      ¬61       "   Insert the string "654321". This will leave the cursor on the '1'
         én     "   Insert an 'n'
           À    "   Run the first arg as V code. This will move left and right a bunch of times
            x   "   Delete whatever character we ended up on
             V  "   Select this whole line,
              p "   And replace it with the character we just deleted

2
また、オンラインでお試しください!V圧縮。カッコいい。
nmjcman101

実際、1/6の上または下に行くとマクロが壊れるため、これは機能しないと思います:/
nmjcman101

9バイトの回答が許可されないのはなぜですか?
アルバートレンショー

@AlbertRenshaw 1速または6速を超えてシフトしようとすると失敗します。たとえば、オンラインでお試しください!nではなく、出力する必要があります1
DJMcMayhem

なるほど、入力によって、あなたは非シフトキャラクターを意味するのは常に有効だと思いました。無効な場合でもまだクールな答え
アルバートレンショー

6

Java 7、106 105 103バイト

char c(String s){int r=1;for(int c:s.toCharArray())r+=c<99?1:-1;return"1N23456".charAt(r<0?0:r>6?6:r);}

説明:

char c(String s){                // Method with String input and character return-type
  int r = 1;                     // Result-index (0-indexed and starting at 1)
  for(int c : s.toCharArray()){  // Loop over all characters in the input String
    r += c < 99 ?                //  If the current character is '^':
           1                     //   Raise the result-index by 1
         :                       //  If it is 'v' instead:
           -1;                   //   Decrease the result-index by 1
  }
  return "1N23456".charAt(       // Return the character based on the return-index:
           r < 0 ?               //  If the result-index is below 0
                  0              //   Use 0 instead
                 : r > 6 ?       //  Else-if the result-index is above 6
                          6      //   Use 6 instead
                         :       //  Else
                          r);    //   Use the result-index
}

テストコード:

ここで試してみてください。

class M{
  static char c(String s){int r=1;for(int c:s.toCharArray())r+=c<99?1:-1;return"1N23456".charAt(r<0?0:r>6?6:r);}

  public static void main(String[] a){
    System.out.println(c("v^^"));
    System.out.println(c("^^^^^^^^"));
    System.out.println(c("vvvv^^^vvvv"));
    System.out.println(c("^v^v^v^v"));
  }
}

出力:

2
6
1
N

5

Haskell、59 53 51バイト

("1N23456"!!).foldl(\l c->max 0$min 6$l+read[c]-1)1

0ダウンと2アップに使用します。使用例:

(("1N23456"!!).foldl(\l c->max 0$min 6$l+read[c]-1)1) "0002"

6バイトを削除してくれた@xnorに感謝します!また、関数名や括弧は必要ないので、もう2バイト必要です。


入力文字を0および2として使用すると、を実行できますread[c]-2
XNOR

PPCGへようこそ!無名関数も問題ないので、を必要としませんg=
ライコニ

@Laikoniかっこで囲む必要がありますよね?私は私が去るだろうと思ったので、それはバイト数を変更しないだろうg=、それは明確だから
user1472751


4

JavaScript(ES6)、48 58バイト

s=>"1N23456"[[1,...s].reduce((a,b)=>a?a<6?+b?a+1:a-1:6:0)]

使用法

関数に割り当ててから呼び出します。入力は、1アップシフト0用とダウンシフト用のa を含む文字列です。

f=s=>"1N23456"[[1,...s].reduce((a,b)=>a?a<6?+b?++a:a--:6:0)]
f("011")
-> "2"
f("0")
-> "1"
f("01")
-> "N"

F(0)を返す1ないN ...そしてあなたのコードに戻りundefをあなたは1から6または下から上にシフトした場合
fənɛtɪk

良いキャッチ。2バイトのコストで修正
ルーク

Nf("001")を返すような入力(
ギアダウン

ループすることは想定されていません。6からアップシフトする場合は6に、1からダウンシフトする場合は1に留まる必要があります。また、1からダウンシフトする場合はundefを与える必要があります
fəˈnɛtɪk

4

PHP 7.1、71バイト

for(;$c=$argv[1][$i++];))$g=max(-1,min($g+=$c<=>X,5));echo N234561[$g];

$g-1から5にシフトすると、最初のギアに負のストリングオフセットが使用されます。
で実行し-nr、シフトする文字列をコマンドライン引数として指定します。


4

ゼリー17 14バイト

1;r2ị$¥/CỊ¡o”N

6アップと0ダウンに使用します。

オンラインでお試しください!

使い方

1;r2ị$¥/CỊ¡o”N  Main link. Argument: s (string of 6's and 0's)

1;              Prepend a 1 (integer) to the string/character array s.
       /        Reduce the result by the following dyadic link.
                Let's call the arguments x and y.
      ¥           Create a dyadic chain of 2 links:
  r                 Construct the range [x, ..., y] (increasing or decreasing).
                    y will be a character, but 'r' casts both argument to int.
                    This is intended for use with floats, but it works just as well
                    when the argument is a digit.
     $              Create a monadic chain of two links:
   2ị                 Take the second element of the constructed range.
                  When y = 6 > x, this gives x + 1.
                  When y = 0 < x, this gives x - 1.
                  When y = x, the range is a singleton array, so this gives x.
          ¡     Conditional application:
         Ị        If the previous result is insignificant (0 or 1):
        C           Subtract it from 1.
                This swaps 0 and 1 without affecting the other potential outcomes.
           o”N  Logical OR with 'N', replacing 0 with that character.

2

ルビー、58バイト

->s{a=1;s.chars{|b|a-=[a<=>0,a<=>6][b<=>?v]};"1N23456"[a]}

予想される入力は、ダウンシフトの場合は「v」、アップシフトの場合は「^」です


2

JSの処理(変更)121バイト

var g="1N23456",a="",c=0; for(var i=0;i<a.length;i++){if(a[i]==="d"&&c>0){c--;}else if(c<6&&a[i]==="u"){c++;}}println(g[c]);

非ゴルフ

var g=[1,"N",2,3,4,5,6],a="",c=0;
for(var i=0;i<a.length;i++)
{if(a[i]==="d"&&c>0)
{
    c--;

}else if(c<6&&a[i]==="u")
{
    c++;

}

}
println(g[c]);

オンラインでお試しください!

私はそれをよく知っているので、私はPJと一緒に行きました。唯一の問題は、使用するバージョンが非常に厳密に入力されていることです。括弧や他の多くのトリックを省くことはできません。とても簡単です。入力は変数に入り、a小文字を取りますu d。プログラムは、文字列の終わりに達するまでループし、繰り返しごとにauかdかを確認します。それがあり、あなたができるところを過ぎて「シフト」しようとしない場合、それはシフトします。最後に結果を印刷します!


あなたのバージョンが三項演算子を許可している場合、もっと短い方法でifを書き換えることができるかもしれません。
ボジダルマリノフ

The input should go into the variable aハードコードされた入力の使用は、デフォルトの入力方法ではありません。こちらを参照してください
ライコニ

@ライコニは本当に?それはばかげています。これ以上良い方法はありません。これをやり直す必要がある場合は、最大で100バイト長くなります
クリストファー

コードを関数で単純にラップすることはできませんか?例えば。void f(String[] a){...}それはほとんど100バイトではありません。
ライコニ

@Laikoni Khan Academy ProcessingJSでは、純粋な JSであるため、Stringまたはvoidがありません。しかし、あなたは正しい、機能は道短いだろう
KritixiのLithos

2

k、25バイト

"1N23456"@{6&0|x+y-92}/1,

入力を文字列として受け取り、便利な位置にあるため、[ダウンシフトと]アップシフトに使用します。

"1N23456"@                / the numbers 0 to 6 are used for the gears,
                          / this turns them into the correct number/letter
                       1, / prepend 1 because this is our initial gear
          {          }/   / fold the function through the list
                          / x is before, y is the next character
                 y-92     / subtract 92, which is between "[" and "]"
                          / "[" becomes -1 and "]" becomes 1
               x+         / add it to what we had before
           6&0|           / use max and min to set boundaries 6 and 0

例:

 shift:"1N23456"@{6&0|x+y-92}/1,
 shift"[]]"
"2"
 shift"]]]]]]]]"
"6"
 shift"[[[[]]][[[["
"1"
 shift"[][][][]"
"N"
 shift"[[[[[[[[]"
"N"
 shift"]]]]]]]]["
"5"

2

GNU sed89 87 + 1(rフラグ)= 88バイト

sedには整数型や算術演算がないため、正規表現のみを使用することで解決できます。

s:$:65432Nx1:
:
/6x/!s:^U(.*)(.)x:\1x\2:
s:^D(.*)x(.):\1\2x:
t
s:U|D::
t
s:.*(.)x.*:\1:

x各入力シフト、左(Upの場合)または右(D独自の場合)に基づいて、セルのみを含む非ラッピングテープに沿ってポインターをスライドさせることにより機能します。65432N1。最後の答えは、ポインターの左のセルの値です。

実行例:またはオンラインで試してみてください!

sed -rf gear.sed <<< "UUUUUUD"
5

説明:

s:$:65432Nx1:              # assign initial tape and pointer
:                          # start loop
/6x/!s:^U(.*)(.)x:\1x\2:   # if shift 'U', slide `x` to left, but not past the edge
s:^D(.*)x(.):\1\2x:        # if shift 'D', slide `x` to right, -||-
t                          # repeat
s:U|D::                    # if a shift couldn't be applied, delete it "manually",
t                          # and jump to the start of the loop again
s:.*(.)x.*:\1:             # print value left of pointer `x` (answer)

76バイトですが、単項で出力されます。
ライリー

@Riley Unary、もちろん!さて、あなたの解決策は異なるので、投稿してみませんか!
seshoumara

あなたのインスピレーションをくれました。必要に応じて使用できると考えました。
ライリー

@Rileyそれから、あなたのバージョンで別のセクションを作り、あなたにクレジットします。
seshoumara

私は自分自身を投稿します:)
ライリー

2

GNU sed76 73バイト

+1を含む -r

s/$/1/
:
/1{6}/!s/^U(.*)/\11/
s/^D(.*)1/\1/
t
s/U|D//
t
s/^1$/N/
s/^$/1/

出力は、中立を除いて単項であり、中立ですNこのコンセンサスを参照)。

オンラインでお試しください!

これは基本的に単項で増減し、1をNに、0を1に変換します。

s/$/1/               # add 1 to the end (the starting value)
:                    # loop start
/1{6}/!s/^U(.*)/\11/ # If the string starts with 'U' and doesn't have 6 ones, increment
s/^D(.*)1/\1/        # If the string starts with 'D' decrement (but not past 0)
t                    # if something changed loop back
s/U|D//              # if the U or D couldn't be applied, remove it.
t                    # if something changed loop back
s/^1$/N/             # replace 1 with N
s/^$/1/              # if "0", replace with 1

sedバージョンは1、開始値としてasを使用しN、as を使用しない場合、4バイト短くすることができます1s/$/1/;:;/1{6}/!s/^U(.*)/\11/;s/^D(.*)1/\1/;t;s/U|D//;t;s/^1$/N/;s/^$/1/
seshoumara

2

Rebol、96 93バイト

f: func[s][g: next"1N23456"parse s[any["D"(g: back g)|"U"(unless tail? x: next g[g: x])]]g/1]

ゴルフをしていない:

f: func [s] [
    g: next "1N23456"
    parse s [
        any [
              "D" (g: back g)
            | "U" (unless tail? x: next g [g: x])
        ]
    ]
    g/1
]

使用例(Rebolコンソール内):

>> print f "DUU"         
2

>> print f "DDDUU"
2

>> print f "UUUUUUUUU"  
6

>> print f "UUUUUUUUUD"
5

2

> <>、35バイト

制限速度を超えて運転することを奨励する熱心なコード。

3を法とするコードが0と2の2つの入力を受け入れます(例:0および)2
余分な魚臭さのために、<との使用をお勧めします>

1i:0(?;3%1-+:0(?0:6)?6:1go!
1N23456

説明 :

1i:0(?;3%1-+:0(?0:6)?6:1go!
1                             # initial position
 i                            # read the next char
  :0(?;                       # copies it, test copy against 0, if lower stops (EOF detection)
       3%1-                   # map the char to -1 or 1
           +                  # add it to the position
            :0(?0             # if the new position is lower than 0, set to 0
                 :6)?6        # if the new position is greater than 6, set to 6
                      :1go    # output a character from line 1 at the position
                          !   # loops and skip the position initialisation

ここで試すことができます


1

SpecBAS-102

1 g=2: INPUT s$
2 FOR i=1 TO LEN s$
3 g+=(s$(i)="^" AND g<7)-(s$(i)="v" AND g>1)
4 NEXT i
5  ?"1N23456"(g)

入力に応じて文字列のインデックスを移動し、関連する文字を出力します。


1

Pyth、32バイト

J1VQ=JhtS[06+J-qNbqNd;?qJ1\N?JJ1

上下にスペースと改行を使用します。

説明

J1VQ=JhtS[06+J-qNbqNd;?qJ1\N?JJ1
J1                                 Initialize J to 1
  VQ                 ;             For each character in the input
            +J-qNbqNd              Increment or decrement J
      htS[06                       Get the middle sorted value of [0,6,J]
    =J                             Assign it to J
                      ?qJ1\N?JJ1   Change 1 to 'N' and 0 to 1

ほぼ確実に、インクリメントと出力を行うより良い方法があります。


1

CJam24 22バイト

"1N23456"1q{~0e>6e<}/=

(ダウンと)アップに使用します。

オンラインでお試しください!

説明

"1N23456"               e# Push the string containing all gears
         1              e# Push 1, the initial index
          q             e# Push the input
           {            e# For each character in the input
            ~           e#   Eval that character. ( is decrement and ) is increment.
             0e>        e#   Take the maximum of (0, index)
                6e<     e#   Take the minimum of (6, index)
                   }/   e# (end of block)
                     =  e# Take that index of the string

1

バッチ、144バイト

@set/ps=
@set g=1
:l
@if %g% neq %s:~,1% set/ag+=%s:~,1%/3-1
@set s=%s:~1%
@if not "%s%"=="" goto l
@if %g%==1 (echo N)else cmd/cset/ag+!g

STDINで入力を受け取り0、より低いギア6に移動し、より高いギアに移動するために使用します。これらの数値は、現在のギアを簡単に無視できるように選択されています。ギアである場合、最終的に1、次にNそれ以外の場合印刷さ0に変換され、1そしてギアが印刷されます。


0

Javascript ES6非厳密、136 120文字

136文字 V^

with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}})f=s=>eval(s.replace(/(V)|./g,(m,v)=>`x${"-+"[+!v]}=1,`,y=1)+'"1N"[x]||x')

with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}})
f=s=>eval(s.replace(/(V)|./g,(m,v)=>`x${"-+"[+!v]}=1,`,y=1)+'"1N"[x]||x')
console.log(f("V^^"))

120文字 -+

with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}})f=s=>eval(s.replace(/./g,m=>`x${m}=1,`,y=1)+'"1N"[x]||x')

with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}})
f=s=>eval(s.replace(/./g,m=>`x${m}=1,`,y=1)+'"1N"[x]||x')
console.log(f("-++"))


0

網膜、65バイト

^
1 N23456
+(` (.)?(\w*6)u
$1 $2
)`(.)? (\w*6)d
 $1$2
.* (.).*
$1

用途 ud上下ため。

オンラインでお試しください!

説明

このプログラム1N23456は、一連の命令を保持することで機能します。背後にスペースを確保することで、現在のギアを追跡します。その後、それ以上なくなるまで、一度に1つの命令を取ります。

^
1 N23456

1 N23456入力の前に置くことから始めます。前のスペースは、NそれNが現在のギアであることを示しています。


+(` (.)?(\w*6)u
$1 $2
)`(.)? (\w*6)d
 $1$2

これらは2つの置換ステージで、グループ化され、文字列の変更が停止するまで実行されます。

 (.)?(\w*6)u
$1 $2

最初の1つは、ギアのシフトアップを処理します。スペースの後に任意の数のギアを探し6、その後に、続いてuuギアシフトアップの指示を示します)。6の前に文字があった場合、その直後の文字とスペースを交換し、を削除してu、文字列の残りをそのまま残します。以来6試合で必須であり、それだけで前に任意の文字とスペースを交換します6。それは決して交換しません6

(.)? (\w*6)d
 $1$2

2番目の段階では、ギアのシフトダウンを処理し、同様に機能します。必要に応じて、スペースの前の文字を探し、次にで終わる他のギアを探し6、その後にd。スペースの前の文字とスワップし、を削除してd、残りをそのまま残します。スペースが文字列の先頭にある場合、スペースの前の文字に一致するものはなかったため、スワップは発生しません。


.* (.).*
$1

上記の交換のいずれももうできなくなった後、すべてのギアシフトが完了しました。スペースの直後のギア以外のすべての行がクリアされます。これが最終ギアです。


0

Powershell、112 87 85バイト

$i=1;switch([char[]]$args[0]){'^'{if(5-gt$i){$i++}}'v'{if(1-le$i){$i--}}}'1N2345'[$i]

食べない

$i=1;                                # index which gear we are in
switch([char[]]$args[0]){            # loop over all elements using a switch
  '^'{if(5-gt$i){$i++}}             # if there is a ^ and we are not in sixth yet, shift up
  'v'{if(1-le$i){$i--}}             # if there is a v and we are not in first, shift down
}
'1N2345'[$i]                         # print the output

powershell codegolfのヒントを読んで25バイトを節約しました

gt / le演算子を反転することで2バイトを節約しました


0

Perl 6、144バイト

my enum C <1 N 2 3 4 5 6>;my $n=prompt("");my $p=1;for split("",$n) ->$l {$l eq "u" && $p < 6 ?? ++$p !! 0;$l eq"d"&&$p>0 ?? --$p!!0};say C($p);

本来どおりに機能すると思います。改善は大歓迎です。初めてPerlを使って何かをしましたが、言語の考え方が大好きだったので、試してみました。


0

Clojure、74バイト

#((vec "1N23456")(reduce(fn[c s](max 0(min 6((if(= s \^)inc dec)c))))1 %))

シフト文字列を折り返し、インデックスをアキュムレーターとして維持します。反復するたびにインデックスが増加または減少し、0〜6の範囲に固定されます。最後に、歯車を保持する文字列にインデックスが付けられて返されます。

現在のギアを表すClojureキャラクターを返します。ギア1はとして返され\1、ギア 'N'はとして返されます\Nます。

ゴルフ前の説明。トップダウンで読みにくいため、数字に従ってください。

; Expects ^ for shift-up, and V (or anything else) for shift down
; Returns a character representing the current gear
(defn shift [shift-str]
  ((vec "1N23456") ; 4. Then index the gear list with the calculated index, and return
   (reduce (fn [current-gear s] ; 1. Fold over the shift symbols
             (max 0 (min 6 ; 3. Clamp it to the range 0-6 so we don't overflow
                      ((if (= s \^) inc dec) ; 2. If the shift is up, increase, else decrease
                       current-gear))))
           1
           shift-str)))

0

Python 3、67 63バイト

k=1
for i in input():k+=[k<6,-(k>0)][i<'1']
print('1N23456'[k])

非常に簡単なソリューション。

@ovsのおかげで-4バイト!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.