Keep/Drop/Increase Sequence

20

0

Here is the sequence I'm talking about:

{1, 4, 5, 9, 10, 11, 16, 17, 18, 19, 25, 26, 27...}

Starting from 1, keep 1, drop the next 2, keep the next 2, drop 3, keep 3 and so on. Yes, it's on OEIS (A064801), too!

The Challenge

Given an integer n>0, find the nth term of the above sequence

Test Cases

Input -> Output       
1->1  
22->49  
333->683
4444->8908
12345->24747

This is code golf so the shortest answer in bytes wins! Good luck!

user73398

Posted 2017-08-21T15:00:13.283

Reputation:

related – Rod – 2017-08-21T15:01:19.013

3May we choose between 0 and 1 indexing? – Mr. Xcoder – 2017-08-21T15:01:59.523

1@Mr.Xcoder I'm afraid not. This is only 1-indexed – None – 2017-08-21T15:04:25.773

May we return a list containing all the elements in order? – Post Rock Garf Hunter – 2017-08-21T15:51:04.893

@WheatWizard this is totally unacceptable. sorry – None – 2017-08-21T16:06:16.927

Answers

12

Java (OpenJDK 8), 45 44 bytes

n->{int i=0;for(;++i<n;n-=i);return~-n+i*i;}

Try it online!

-1 byte thanks to @Nevay

After staring at this for a while, I noticed a pattern. Every time we drop n numbers, the next number in the sequence is a perfect square. Seeing this, I mentally broke the sequence into convenient chunks: [[1],[4,5],[9,10,11],...] Basically, the ith chunk starts with i*i, and iterates upwards for i elements.

To find the nth number in this sequence, we want to find first which chunk the number is in, and then which position in the chunk it occupies. We subtract our increment number i from n until n is less than i (which gives us our chunk), and then simply add n-1 to i*i to get the correct position in the chunk.

Example:

n = 8
n > 1? Yes, n = n - 1 = 7
n > 2? Yes, n = n - 2 = 5
n > 3? Yes, n = n - 3 = 2
n > 4? No, result is 4 * 4 + 2 - 1 = 17

Xanderhall

Posted 2017-08-21T15:00:13.283

Reputation: 1 236

1You can use return~-n+i*i; to save 1 byte. – Nevay – 2017-08-22T11:43:43.363

7

Haskell, 48 43 41 bytes

n#l=[l..l+n]++(n+1)#(l+2*n+3)
((0:0#1)!!)

4 extra bytes for 1-based indexing instead of 0-based. An unnecessary restriction, IMHO.

Try it online!

n#l             -- n is one less than the number of element to keep/drop and
                -- l the next number where the keep starts
   [l..l+n]     -- keep (n+1) numbers starting at l
   ++           -- and append a recursive call
   (n+1)#       -- where n is incremented by 1 and
      (l+2*n+3) -- l skips the elements to keep & drop

0#1             -- start with n=1 and l=0 and
 0:             -- prepend a dummy value to shift from 0 to 1-based index
    !!          -- pick the i-th element from the list 

nimi

Posted 2017-08-21T15:00:13.283

Reputation: 34 639

6

Python 3, 47 46 bytes

1 byte thanks to Mr. Xcoder.

def f(n):a=round((2*n)**.5);return~-n+a*-~a//2

Try it online!

VERY fast for higher numbers

Leaky Nun

Posted 2017-08-21T15:00:13.283

Reputation: 45 011

46 bytes: def f(n):a=round((2*n)**.5);return~-n+a*-~a//2. Not sure though... Clever approach! – Mr. Xcoder – 2017-08-21T15:15:08.867

Aw, double lambdas is one extra byte, I was hoping that would save a byte... – Stephen – 2017-08-21T15:21:24.360

Why did one downvote this? Is there any problem with the approach that we didn't notice? – Mr. Xcoder – 2017-08-21T15:24:45.153

@Mr.Xcoder maybe because of the corky remark. – Leaky Nun – 2017-08-21T15:28:16.777

a*(a+1) is even for every integer. Does Python complain about float division on integers? Does it complain about bitwise operations on floats? If not: (2*n)**.5+.5|0. – Titus – 2017-08-22T13:42:44.190

3

Jelly, 8 bytes

Ḷ+²µ€Ẏ⁸ị

Try it online!

Erik the Outgolfer

Posted 2017-08-21T15:00:13.283

Reputation: 38 134

3

Haskell, 33 bytes

An anonymous function. Use as ((!!)$0:do n<-[1..];[n^2..n^2+n-1]) 1

(!!)$0:do n<-[1..];[n^2..n^2+n-1]

Try it online!

  • Constructs the sequence as an infinite list, then indexes into it with !!. The 0: is a dummy element to adjust from 0- to 1-based indexing.
  • The range [n^2..n^2+n-1] constructs a subsequence without gaps, starting with the square of n and containing n numbers.
  • The do notation concatenates the constructed ranges for all n>=1.

Ørjan Johansen

Posted 2017-08-21T15:00:13.283

Reputation: 6 914

2

Python 3, 46 bytes

f=lambda x,y=0,z=0:y<x and f(x,y+z,z+1)or~-y+x

Try it online!

Mr. Xcoder

Posted 2017-08-21T15:00:13.283

Reputation: 39 774

Same algorithm... – Leaky Nun – 2017-08-21T15:45:24.020

2

Perl 6, 43 bytes

{(1..*).rotor({++$=>++$+1}...*).flat[$_-1]}

Test it

Expanded:

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

  ( 1 .. * )                  # range starting from 1

  .rotor(                     # break it into chunks

    { ++$  =>  ++$ + 1} ... * # infinite Seq of increasing pairs
    #   1  =>    1 + 1    ==>   1 => 2 ( grab 1 skip 2 )
    #   2  =>    2 + 1    ==>   2 => 3
    #   3  =>    3 + 1    ==>   3 => 4
    # ...  =>  ... + 1

  ).flat\                     # reduce the sequence of lists to a flat sequence
  [ $_ - 1 ]                  # index into the sequence
                              # (adjusting to 0-based index)
}

(1..*).rotor({++$=>++$+1}...*) produces:

(
 (1,),
 (4, 5),
 (9, 10, 11),
 (16, 17, 18, 19),
 (25, 26, 27, 28, 29),
 ...
).Seq

Brad Gilbert b2gills

Posted 2017-08-21T15:00:13.283

Reputation: 12 713

2

TeX, 166 bytes

\newcommand{\f}[1]{\count0=0\count1=0\loop\advance\count0 by\the\count1\advance\count1 by1\ifnum\count0<#1\repeat\advance\count0 by#1\advance\count0 by-1
\the\count0}

Usage

\documentclass[12pt,a4paper]{article}
\begin{document}
\newcommand{\f}[1]{\count0=0\count1=0\loop\advance\count0 by\the\count1\advance\count1 by1\ifnum\count0<#1\repeat\advance\count0 by#1\advance\count0 by-1
\the\count0}

\f{1}

\f{22}

\f{333}

\f{4444}

\f{12345}
\end{document}

enter image description here

Leaky Nun

Posted 2017-08-21T15:00:13.283

Reputation: 45 011

2

Javascript, 43 38 bytes

n=>eval("for(r=1;n>r;)n-=r++;r*r+n-1")

Try it online!

I use the fact, that for each triangular number plus one, the result is a square number.

As an example: triangular numbers are 0, 1, 3, 6, 10... so for 1, 2, 4, 7, 11... we observe 1, 4, 9, 16, 25... in our sequence.

If the index is somewhere between these known numbers, the elements of our sequence only advance by one. For instance, to calculate the result for 10, we take 7 (as a triangular number plus one), take the result (16) and add 10-7=3. Thus, 16+3=19.

mackoo13

Posted 2017-08-21T15:00:13.283

Reputation: 61

1

05AB1E, 12 bytes

LεÝÁćn+}˜¹<è

Try it online!

Erik the Outgolfer

Posted 2017-08-21T15:00:13.283

Reputation: 38 134

Very cool approach! – Emigna – 2017-08-21T20:55:14.583

@Emigna Well, I'm just doing [0..a-1] + a**2, the cool thing here imo is just the ÝÁćn+ instead of D<Ýsn+. – Erik the Outgolfer – 2017-08-22T07:47:26.087

1

cQuents, 27 bytes

#R(2B)^.5)|1:b~-B+A*-b~A//2

Try it online!

Currently a port of Leaky's Python answer, I think there's a better way though.

Stephen

Posted 2017-08-21T15:00:13.283

Reputation: 12 293

Try my alternative algorithm – Leaky Nun – 2017-08-21T15:31:02.453

1

Swift 3, 72 bytes

Port of my Python solution.

func f(_ x:Int,_ y:Int=0,_ z:Int=0)->Int{return y<x ?f(x,y+z,z+1):y+x-1}

Test Suite.

Mr. Xcoder

Posted 2017-08-21T15:00:13.283

Reputation: 39 774

1

C# (Mono), 164 bytes

using System.Linq;n=>{var a=new int[1]{1}.ToList();for(int i=1,m;a.Count<n;a.AddRange(new int[++i*2].Select((_,d)=>m+d+1).Skip(i).Take(i)))m=a.Max();return a[n-1];}

Try it online!

TheLethalCoder

Posted 2017-08-21T15:00:13.283

Reputation: 6 930

1

Mathematica, 37 bytes

Flatten[Range@#+#^2-1&~Array~#][[#]]&

Explanation

Range@#+#^2-1&

Function which takes a positive integer # and returns the run of # consecutive numbers in the sequence.

...~Array~#

Produces the list of all such runs up to the input #

Flatten[...][[#]]

Flattens the resulting list and returns the #th element.

ngenisis

Posted 2017-08-21T15:00:13.283

Reputation: 4 600

1

Perl 5, 33 + 1 (-p) = 34 bytes

$\+=$.--?1:2+($.=++$s)while$_--}{

Try it online!

Xcali

Posted 2017-08-21T15:00:13.283

Reputation: 7 671

1

Tampio, 310 308 bytes

n:n uni on n unena 1:lle
a unena k:lle on a vuona k:lla vähennettynä a:sta ja k
a vuona nollalla ja k on a
a vuona k:lla vähennettynä nollasta ja k on a
a vuona b:n seuraajalla ja k on yhteenlaskun kutsuttuna k:n kerrottuna 2:lla arvolla ja k:n vähennettynä a:sta arvolla unena k:n seuraajalle seuraaja

Usage: 4:n uni evaluates to 9.

Explanation:

n:n uni on n unena 1:lle
uni(n)  =  n `uni` 1

a unena k:lle on  a vuona  k:lla vähennettynä a:sta ja k
a `uni` k     =  (a `vuo` (k     `vähennetty` a)    )  k

 a vuona nollalla ja k on a
(a `vuo` 0        )  k =  a

 a vuona  k:lla vähennettynä nollasta ja k on a
(a `vuo` (k     `vähennetty` 0)       )  k =  a

 a vuona  b:n seuraajalla ja k on
(a `vuo` (b   + 1)        )  k =

 yhteenlaskun kutsuttuna k:n kerrottuna 2:lla arvolla
(yhteenlasku            (k   *          2     )

 ja k:n vähennettynä a:sta arvolla unena  k:n seuraajalle seuraaja
((  k   `vähennetty` a     )       `uni` (k   + 1)   )  ) + 1

From standard library:

a `vähennetty` b = b - a
yhteenlasku a b  = a + b

fergusq

Posted 2017-08-21T15:00:13.283

Reputation: 4 867

1

JavaScript (ES6), 33 bytes

Recursive solution inspired by Xanderhall's observations.

f=(n,x=1)=>n<x?n+x*x-1:f(n-x,++x)

Try it

o.innerText=(
f=(n,x=1)=>n<x?n+x*x-1:f(n-x,++x)
)(i.value=12345);oninput=_=>o.innerText=f(+i.value)
<input id=i type=number><pre id=o>

Shaggy

Posted 2017-08-21T15:00:13.283

Reputation: 24 623

0

Python 3, 50 bytes

def f(n):
 a=i=0
 while a<n:a+=i;i+=1
 return~-a+n

Try it online!

Leaky Nun

Posted 2017-08-21T15:00:13.283

Reputation: 45 011

This would really benefit from a full-program port to Python 2 (46 bytes - would tie the recursive approach)

– Mr. Xcoder – 2017-08-21T15:37:34.367

0

Mathematica, 82 bytes

Complement[Range[3#],Array[#+⌊((r=Sqrt[1+8#])-1)/2⌋⌊(r+1)/2⌋/2&,3#]][[#]]&

J42161217

Posted 2017-08-21T15:00:13.283

Reputation: 15 931

0

Python, 40 bytes

lambda n:(round((2*n)**.5)+.5)**2//2+n-1

Try it online!

Optimizing Leaky Nun's expression.


Python, 41 bytes

f=lambda n,k=1:n*(n<=k)or-~f(n-k,k+1)+2*k

Try it online!

Recursive expression.

xnor

Posted 2017-08-21T15:00:13.283

Reputation: 115 687

0

Javascript (ES6) 100 98 Bytes

var k=n=>{var s=[],i=1,c=1,j;while(s.length<n){for(j=i;j<i+c;j++){s.push(j)}i+=c*2+1;c++}return s}

Kind of did this one fast, so I bet there is a lot of room for improvement, just basic loops and counters.

Asleepace

Posted 2017-08-21T15:00:13.283

Reputation: 311

0

Retina, 27 bytes

.+
$*
((^1|1\2)+)1
$1$2$&
1

Try it online! Port of @LeakyNun's Python answer. The first and last stages are just boring decimal ⇔ unary conversion. The second stage works like this: ((^1|1\2)+) is a triangular number matcher; $1 is the matched triangular number while $2 is its index. The trailing 1 means it matches the largest triangular number strictly less than the input, thus resulting in exactly one fewer iteration than the Python loop, meaning that $1 is equivalent to a-i and $2 to i-1 and their sum is a-1 or ~-a as required. ($& just prevents the match from being deleted from the result.) Note that for an input of 1 no matching happens and the output is simply the same as the input. If you were perverse you could use ^((^1|1\2)*)1 to match in that case too.

Neil

Posted 2017-08-21T15:00:13.283

Reputation: 95 035

0

MATL, 12 bytes

:"@U@:q+]vG)

Try it online!

Explanation

:        % Push range [1 2 ... n], where n is implicit input
"        % For each k in that range
  @U     %   Push k^2
  @:     %   Push range [1 2 ... k]
  q      %   Subtract 1: gives [0 1 ... k-1]
  +      %   Add: gives [k^2 k^2+1 ... k^2+k-1]
]        % End
v        % Concatenate all numbers into a column vector
G)       % Get n-th entry. Implicitly display

Luis Mendo

Posted 2017-08-21T15:00:13.283

Reputation: 87 464

0

C (gcc), 38 bytes

Using @Xanderhall's algorithm here

i;f(n){for(i=0;++i<n;n-=i);n=n-1+i*i;}

Try it online!

cleblanc

Posted 2017-08-21T15:00:13.283

Reputation: 3 360

0

PHP, 48 42 37+1 bytes

ported from Leaky Nun´s answer

while($argn>$a+=$i++);echo$a+~-$argn;

Run as pipe with -F or try it online.

direct approach, 42+1 bytes (ported from Leaky Nun´s other answer)

<?=($a=(2*$argn)**.5+.5|0)*-~$a/2+~-$argn;

Run as pipe with -nR or uncomment in above TiO.

older iterative solution, 48+1 bytes

for(;$argn--;$n++)$c++>$z&&$n+=++$z+$c=1;echo$n;

Titus

Posted 2017-08-21T15:00:13.283

Reputation: 13 814