可能な限り多くの数字で増加するシーケンスを埋める


29

すべての要素がその前の要素以上である場合、数字のリストは単調増加(または非減少)と呼ばれます。

たとえば、1, 1, 2, 4, 5, 5, 5, 8, 10, 11, 14, 14単調に増加しています。

で示される任意の数の空のスポットを持つ単調に増加する正の整数のリストが与えられると、?空のスポットを正の整数で埋めて、リストにできるだけ多くの一意の整数が存在するようにしますが、単調に増加したままです。

これを実現する方法は複数あります。いずれも有効です。

結果のリストを出力します。

たとえば、入力が

?, 1, ?, 1, 2, ?, 4, 5, 5, 5, ?, ?, ?, ?, 8, 10, 11, ?, 14, 14, ?, ?

空のスポットがないと、リストが単調に増加することが保証されます

1, 1, 2, 4, 5, 5, 5, 8, 10, 11, 14, 14

そして、あなたの仕事は、正の整数をそれぞれに割り当て?て、リスト内の異なる整数の数を最大化しながら、それを減少させないことです。

無効な割り当ては

1, 1, 1, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 8, 10, 11, 14, 14, 14, 14, 14

なぜなら、それは減少していませんが、入力よりも一意な整数が1つしかないため3です。

この例では、6つの一意の正の整数を挿入し、リストを減少させないことができます。
考えられるいくつかの方法は次のとおりです。

1, 1, 1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 8, 8, 10, 11, 12, 14, 14, 15, 16

1, 1, 1, 1, 2, 3, 4, 5, 5, 5, 5, 6, 6, 7, 8, 10, 11, 13, 14, 14, 20, 200

これらのいずれか(および他の多く)が有効な出力になります。

すべての空のスポットを埋める必要があります。

挿入できる整数に上限はありません。非常に大きな整数が科学表記法で出力されても問題ありません。

ゼロは正の整数ではないため、挿入しないでください。

代わりに、?正の整数でない任意の一貫した値、のような使用することができます0-1nullFalse、またはを""

バイト単位の最短コードが優先されます。

その他の例

[input]
[one possible output] (a "*" means it is the only possible output)

2, 4, 10
2, 4, 10 *

1, ?, 3
1, 2, 3 *

1, ?, 4
1, 2, 4

{empty list}
{empty list} *

8
8 *

?
42

?, ?, ?
271, 828, 1729

?, 1
1, 1 *

?, 2
1, 2 *

?, 3
1, 3

45, ?
45, 314159265359

1, ?, ?, ?, 1
1, 1, 1, 1, 1 *

3, ?, ?, ?, ?, 30
3, 7, 10, 23, 29, 30 

1, ?, 2, ?, 3, ?, 4
1, 1, 2, 3, 3, 3, 4

1, ?, 3, ?, 5, ?, 7
1, 2, 3, 4, 5, 6, 7 *

1, ?, 3, ?, 5, ?, ?, 7
1, 2, 3, 4, 5, 6, 7, 7

1, ?, ?, ?, ?, 2, ?, ?, ?, ?, 4, ?, 4, ?, ?, 6
1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, 6

98, ?, ?, ?, 102, ?, 104
98, 99, 100, 101, 102, 103, 104 *

検証用の厳密な入力と出力のペアを持つ問題を表現するより良い方法は、おそらく「シーケンス内の異なる番号の最大可能数」です。そうすれば、すべての回答が同じ数を出力し、テストケースの評価がはるかに簡単になります
-Cruncher

@StewieGriffinリストの値と長さが通常どおりintの最大値を下回っていると仮定できます。アルゴリズムが機能する方法であれば、最後に非常に大きな整数を挿入してもかまいません。
カルビンの趣味

回答:


11

Haskell、41バイト

fリストを取り、リストを返します。0は?sを表します。

f=scanr1 min.tail.scanl(#)0
m#0=m+1
_#n=n

基本的に、最初のリストを左からスキャンして、0を前の要素よりも1つ多く置き換えます(または、先頭の0)。次に、右からスキャンして、大きすぎる要素を減らして右の要素と等しくします。

オンラインでお試しください!?s を変換するラッパー付き。)


4

Mathematica、84バイト

Rest[{0,##}&@@#//.{a___,b_,,c___}:>{a,b,b+1,c}//.{a___,b_,c_,d___}/;b>c:>{a,c,c,d}]&

空のスポットがNull(のように{1, Null, Null, 2, Null})または完全に削除され(のように)示され{1, , , 2, }、適切なリスト(この場合は{1, 2, 2, 2, 3})を返すリストを引数として取る純粋な関数。

私はØrjanJohansenのHaskellの答えと同じアルゴリズムを使用していることがわかります:最初にNull左の数字よりも1つずつ大きく//.{a___,b_,,c___}:>{a,b,b+1,c}置き換え()、次に大きすぎる数字を右の数字で置き換えます(//.{a___,b_,c_,d___}/;b>c:>{a,c,c,d})。Nullリストの先頭にある可能性のあるs を処理するには、先頭に0{0,##}&@@#)を付け、アルゴリズムを実行してから、最初の0Rest)を削除します。

はい、コード内の文字通り1バイト(そうでなければコンマの間にあるバイト)を保存するNull代わりに、Xまたはそのような何かを選択しましたb_,,c___


うーん、あなたが言う1を前に付けますか?のような理由で、0を使用しました?, 22, 2正しいの代わりにあなたが生産すると思う1, 2
Ørjanヨハンセン

素晴らしい点!幸いなことに、修正は簡単です。
グレッグマーティン

3

C 160

これは決して勝つことはありませんが:

#define p(x)printf("%d ",x);
i=1,l=0,m=0,n;main(c,v)char**v;{for(;i<c;i++)if(*v[i]==63)m++;else{for(n=atoi(v[i]);m>0;m--)p(l<n?++l:n)p(l=n)}for(;m>0;m--)p(++l)}

コマンドライン引数からリストを取得します。



3

05AB1E31 23 13バイト

Grimyのおかげで10バイト節約

ε®X:D>U].sR€ß

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

説明

ε      ]       # apply to each number in input
 ®X:           # replace -1 with X (initially 1)
    D>U        # store current_number+1 in X
        .s     # get a list of suffixes
          R    # reverse
           ۧ  # take the minimum of each

なぜこれは出力の一部だけを印刷するのですか?TIOの例では、最初の1つが欠落しています。
致命的

私はそれがしばらく前であることを知っており、おそらくもう少しゴルフすることができますが、いくつかの簡単なゴルフでは-3バイトです:両方とも2バイト節約}}することができ]ます。そして、õ-)Rすることができ)˜R、追加のバイトを保存します。
ケビンクルイッセン

2
@KevinCruijssen:確かにそれは可能性があります:)
エミナ

1
まだできる!161513
グリムミー

@Grimy:わあ、ありがとう!その接尾辞のトリックは本当にスマートでした!
エミグナ

2

ピップ25 23 21バイト

Y{Y+a|y+1}MgW PMNyPOy

複数のスペースで区切られたコマンドライン引数として入力を受け取ります。結果リストを1行に1つずつ出力します。オンラインでお試しください!(TIOに25個の引数を追加するのは苦痛になるので、複数のコマンドライン引数のことをごまかしましたが、宣伝どおりに機能します。)

説明

2つのパスに進みます。まず、?入力内のsのすべての実行を、リスト内の前の番号から始まり、毎回1ずつ増加するシーケンスに置き換えます。

? 1 ? 1 2 ? 4 5 5 5 ? ? ? ? 8 10 11 ?  14 14 ?  ?
1 1 2 1 2 3 4 5 5 5 6 7 8 9 8 10 11 12 14 14 15 16

その後、再びループします。各番号について、その最小値とすべての番号を右に印刷します。これにより、単調性を維持するには高すぎる数が減少します。

                      y is initially "", which is 0 in numeric contexts
                      Stage 1:
 {       }Mg           Map this function to list of cmdline args g:
   +a                  Convert item to number: 0 (falsey) if ?, else nonzero (truthy)
     |                 Logical OR
      y+1              Previous number +1
  Y                    Yank that value into y (it is also returned for the map operation)
Y                      After the map operation, yank the whole result list into y
                      Stage 2:
            W          While loop, with the condition:
               MNy      min(y)
              P         printed (when y is empty, MN returns nil, which produces no output)
                  POy  Inside the loop, pop the leftmost item from y

2

NumPyを使用したPython 2、163バイト

@wythagorasのおかげで8バイト節約

空のスポットをマークするために使用されるゼロ

import numpy
l=[1]+input()
z=numpy.nonzero(l)[0]
def f(a,b):
 while b-a-1:a+=1;l[a]=l[a-1]+1;l[a]=min(l[a],l[b])
i=1
while len(z)-i:f(z[i-1],z[i]);i+=1
print l[1:]

コメント付きで読みやすく:

import numpy
l=[1]+input()           # add 1 to the begining of list to handle leading zeros
z=numpy.nonzero(l)[0]   # get indices of all non-zero values
def f(a,b):             # function to fill gap, between indices a and b
    while b-a-1:
        a+=1
        l[a]=l[a-1]+1   # set each element value 1 larger than previous element
        l[a]=min(l[a],l[b])   # caps it by value at index b
i=1
while len(z)-i:       
    f(z[i-1],z[i])      # call function for every gap
    i+=1
print l[1:]             # print result, excluding first element, added at the begining

1
いくつかの改善: if l[a]>l[b]:l[a]=l[b]可能性がl[a]=min(l[a],l[b])あり、それからその前の行にあります。また、これは、行全体をの後に置くことができることを意味しwhileます。そして、私は考えるl=input()l=[1]+lすることができl=[1]+input()ます(あなたがインデント2つのレベルを使用する場合は、スペースとタブの代わりにスペースやPython 2で二つのスペースを使用することができます(また、一般的にcodegolf.stackexchange.com/a/58を) )
ウィタゴラス

1
また、len(z)-i:f(z[i-1],z[i]);i+=1i = 1で開始する場合、最後の行の隣にある場合があります。
ウィタゴラス

@wythagoras良いアドバイスありがとうございます。私は、コードにこれを追加しました
デッドポッサム

いいですが、それはわずか163バイトです。
ウィタゴラス

ああ@wythagoras、私は更新バイト数を忘れてしまった
デッドポッサム

1

PHP、95 77 71 69 68バイト

for($p=1;$n=$argv[++$i];)echo$p=$n>0?$n:++$p-in_array($p,$argv)," ";

コマンドライン引数から入力を受け取り、スペースで区切られたリストを出力します。で実行し-nrます。

壊す

for($p=1;$n=$argv[++$i];)   # loop through arguments
    echo$p=                     # print and copy to $p:
    $n>0                            # if positive number
        ?$n                             # then argument
        :++$p                           # else $p+1 ...
            -in_array($p,$argv)         # ... -1 if $p+1 is in input values
    ," ";                       # print space

$n空の文字列と"0"
$n>0正数-およびそれらを含む文字列については真実です。


1

Perl 6、97バイト

{my $p;~S:g/(\d+' ')?<(('?')+%%' ')>(\d*)/{flat(+($0||$p)^..(+$2||*),(+$2 xx*,($p=$2)))[^+@1]} /}

入力は、値のリスト、またはスペースで区切られた文字列のいずれかで、?置換される値を表すために使用されます。

出力は、スペースで区切られた文字列で、末尾にスペースが付きます。

それを試してみてください

拡張:

{                       # bare block lambda with implicit parameter 「$_」

    my $p;              # holds the previous value of 「$2」 in cases where
                        # a number is sandwiched between two replacements

    ~                   # stringify (may not be necessary)
    S                   # replace
    :global
    /
        ( \d+ ' ' )?    # a number followed by a space optionally ($0)

        <(              # start of replacement

          ( '?' )+      # a list of question marks
          %%            # separated by (with optional trailing)
          ' '           # a space

        )>              # end of replacement

        (\d*)           # an optional number ($2)

    /{                  # replace with the result of:

        flat(

          +( $0 || $p ) # previous value or 0
          ^..           # a range that excludes the first value
          ( +$2 || * ), # the next value, or a Whatever star

          (
            +$2 xx *,   # the next value repeated endlessly

            ( $p = $2 ) # store the next value in 「$p」
          )

        )[ ^ +@1 ]      # get as many values as there are replacement chars
    } /                 # add a space afterwards
}

私はPerl 6を知りませんが、Perl 5 $"では' 'バイトを削る代わりに使用できます。ここで機能しますか?
msh210

@ msh210これらの変数のほとんどすべてがなくなっているか、より長い名前を持っています。まだ存在し、同じ目的を持っている唯一のものについてです$!。($/存在するが$1$/[1]$<a>→に使用される$/{ qw< a > }
ブラッドギルバートb2gills

1

JavaScript(ES6)、65バイト

a=>a.map(e=>a=e||-~a).reduceRight((r,l)=>[r[0]<l?r[0]:l,...r],[])

使用したかったからreduceRightです。説明:map各偽の値を前の値よりも1つ多く置き換えます。その後reduceRight、最後から戻り、値が次の値を超えないようにします。


1

Q、63バイト

{1_(|){if[y>min x;y-:1];x,y}/[(|){if[y=0;y:1+-1#x];x,y}/[0,x]]}

ØrjanJohansenのHaskell answerと本質的に同じアルゴリズム。

  • 仮定する?= 0。
  • ?の場合、配列の先頭に0を挿入します 開始時に。
  • 0を1 + previous要素に置き換えて配列をスキャンします。
  • 配列を反転して再度スキャンし、前の要素より大きい要素を前の要素に置き換えます。
  • 最初の要素(先頭から追加された0)を反転して切り取ります。

最後の要素が配列の降順で与えられたmin要素であると仮定できるため、min vs lastを使用して1バイトを節約しました。


クールな答え、サイトへようこそ!:)
DJMcMayhem

1

TI-Basic(TI-84 Plus CE)、81バイト

not(L1(1))+L1(1→L1(1
For(X,2,dim(L1
If not(L1(X
1+L1(X-1→L1(X
End
For(X,dim(L1)-1,1,-1
If L1(X)>L1(X+1
L1(X+1→L1(X
End
L1

TI-Basic に対するØrjanJohansenのHaskell回答の単純な移植版。NULL値として0を使用します。L 1から入力を取得します

説明:

not(L1(1))+L1(1→L1(1 # if it starts with 0, change it to a 1
For(X,2,dim(L1     # starting at element 2:
If not(L1(X              # if the element is zero
1+L1(X-1→L1(X            # change the element to one plus the previous element
End
For(X,dim(L1)-1,1,-1 # starting at the second-last element and working backwards
If L1(X)>L1(X+1           # if the element is greater than the next
L1(X+1→L1(X               # set it equal to the next
End
L1                   # implicitly return

1

Java 8、199 164バイト

a->{for(int l=a.length,n,j,x,i=0;i<l;)if(a[i++]<1){for(n=j=i;j<l;j++)if(a[j]>0){n=j;j=l;}for(j=i-3;++j<n-1;)if(j<l)a[j+1]=j<0?1:a[j]+(l==n||a[n]>a[j]|a[n]<1?1:0);}}

バイトを節約するために新しい配列を返す代わりに、入力配列を変更します。
0代わりに使用します?

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

説明:

a->{                      // Method with integer-array parameter and no return-type
  for(int l=a.length,     //  Length of the input-array
      n,j,x,              //  Temp integers
      i=0;i<l;)           //  Loop `i` over the input-array, in the range [0, length):
    if(a[i++]<1){         //   If the `i`'th number of the array is 0:
                          //   (And increase `i` to the next cell with `i++`)
      for(n=j=i;          //    Set both `n` and `j` to (the new) `i`
          j<l;j++)        //    Loop `j` in the range [`i`, length):
        if(a[j]>0){       //     If the `j`'th number of the array is not 0:
          n=j;            //      Set `n` to `j`
          j=l;}           //      And set `j` to the length to stop the loop
                          //    (`n` is now set to the index of the first non-0 number 
                          //     after the `i-1`'th number 0)
      for(j=i-3;++j<n-1;) //    Loop `j` in the range (`i`-3, `n-1`):
        if(j<l)           //     If `j` is still within bounds (smaller than the length)
          a[j+1]=         //      Set the `j+1`'th position to:
            j<0?          //       If `j` is a 'position' before the first number
             1            //        Set the first cell of the array to 1
            :             //       Else:
             a[j]+        //        Set it to the `j`'th number, plus:
              (l==n       //        If `n` is out of bounds bounds (length or larger)
               ||a[n]>a[j]//        Or the `n`'th number is larger than the `j`'th number
               |a[n]<1?   //        Or the `n`'th number is a 0
                1         //         Add 1
               :          //        Else:
                0);}}     //         Leave it unchanged by adding 0


0

JavaScript(ES6)、59

入力として整数配列を持つ関数。空のスポットには0

a=>a.map((v,i)=>v?w=v:(a.slice(i).find(x=>x)<=w?w:++w),w=0)

テスト

var F=
a=>a.map((v,i)=>v?w=v:(a.slice(i).find(x=>x)<=w?w:++w),w=0)

;[[2, 4, 10]
,[1, 0, 3]
,[1, 0, 4]
,[]
,[8]
,[0]
,[0, 0, 0]
,[0, 1]
,[0, 2]
,[0, 3]
,[45, 0]
,[1, 0, 0, 0, 1]
,[3, 0, 0, 0, 0, 30]
,[1, 0, 2, 0, 3, 0, 4]
,[1, 0, 3, 0, 5, 0, 7]
,[1, 0, 3, 0, 5, 0, 0, 7]
,[1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 4, 0, 0, 6]
,[98, 0, 0, 0, 102, 0, 104]]
.forEach(a=>{
  console.log(a+'\n'+F(a))
})



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