Golfing the Core

5

2

Note: although this is tagged as Python, other languages are permitted

Challenge

What you have to do is write the shortest functions to perform the same actions as the following Python 2 built in functions:

Range

>>> range(1, 10, 1)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(1, 10, 2)
[1, 3, 5, 7, 9]
>>> range(10, 5, -1)
[10, 9, 8, 7, 6]

range(start, end, step)

When run, this produces an ascending list of numbers. Generally used in for loops, this can also be used for golfing when lists of numbers are required.

Type

>>> type(12)
'int'
>>> type(12.0)
'float'
>>> type('12')
'str'
>>> type([13, 45])
'list'

type(var)

Returns the data type of a variable. The required types are in the examples.

Round

>>> round(0.5, 0)
1.0
>>> round(0.2, 0)
0.0
>>> round(3.14159, 3)
3.142
>>> round(127.56, -2)
100.0
>>> round(12.5640, 2)
12.56
>>> round(1457, -2)
1500

round(number, ndigits)

Given a floating point integer, it rounds it to ndigits. Floor and ceil functions are not allowed. For ties, round away from zero.

Enumerate

Note: Return a list despite the fact that in Python, enumerate returns an object.

>>> enumerate([1, 2, 3, 4])
[[0, 1], [1, 2], [2, 3], [3, 4]]
>>> enumerate(['spam', 'eggs'])
[[0, 'spam'], [1, 'eggs']]

enumerate(array)

Returns a two dimensional list with the index as part of the embedded list.

Rules

People writing in Python must not use the built-in functions listed above (or magic variables). If there are similar built-in functions in your language, you must not use them.

For invalid arguments return 1:

>>> enumerate(23)
1
>>> round(56, 'hello')
1
>>> range('hi', 4, 1)
1

You may use your own functions (range, type, round and enumerate).

Winning

Your score is the sum of the byte count for each function (the function declaration should not be counted). The lowest score wins.

Beta Decay

Posted 2014-10-10T17:20:56.510

Reputation: 21 478

Question was closed 2019-11-14T22:45:26.010

The "return 1" imposition generate a ugly bug, because it is possible to confuse one right answer as round(0.5,0) with one not right as round("hi",0) (both one would return 1). For the remain it was a little difficult find the right extreme for range(). In total it is a very good question: Thank you – RosLuP – 2017-11-13T04:30:46.273

Use lambda for 0 bytes? (The entire statement is declaring a function) – pppery – 2019-10-18T20:18:09.613

4

I'm voting to close this question as off-topic because it a multi-part challenge with no interaction between the parts

– pppery – 2019-11-14T04:20:57.170

1How should throw a type error work outside of Python? – Dennis – 2014-10-10T18:15:32.063

@BetaDecay - So CJam's , is allowed ? which works like 10 , = [0 1 2 3 4 5 6 7 8 9] ? – Optimizer – 2014-10-10T18:36:57.983

@Optimizer I'm afraid not – Beta Decay – 2014-10-10T18:57:13.960

Does the range version have to work for fewer arguments? For example, range(5) yields [0,1,2,3,4] and range(2,5) yields [2,3,4]. – Wrzlprmft – 2014-10-12T20:08:46.427

@Wrzlprmft No, to be fair on other languages, it must use three arguments – Beta Decay – 2014-10-12T20:09:22.430

So, I may not even write a version of range which is capable of dealing with fewer arguments, if I want to? – Wrzlprmft – 2014-10-12T20:11:35.720

@Wrzlprmft Well... Go on then – Beta Decay – 2014-10-12T20:12:21.730

Are you sure about having 1 returned for invalid arguments? Most solutions do not seem to comply with this. – Wrzlprmft – 2014-10-12T22:52:15.210

Answers

3

Python 2 – 309 303

t=type=lambda x:["list","string","int","float"][(`x`[0]!="[")*(1+(`x`[0]!="'")*(1+("."in`x`)))]
def T(s,a,i,b=1):
    try:return(1/(t(i)=='int'))*eval(s)
    except:return 1
r=range=lambda a,b,i:T("[a]+r(a+i,b,i)if b*i>a*i else[]",a,i,b)
enumerate=lambda a:T("map(list,zip(r(0,len(a),1),a))",a,1)
def round(a,i):b=T("10.**-i/2*a/abs(a)",a,i);return T("a-(a+b)%(b*2)+b",a,i,b)

It’s so long, because it complies with the requirements (if I am not mistaken), in particular returning 1 for invalid input.

Matsjoyce’ answer provided some inspirations.

Wrzlprmft

Posted 2014-10-10T17:20:56.510

Reputation: 2 772

This is the shortests valid answer (out of this and the Applescript answer), so I've accepted it – Beta Decay – 2014-11-09T00:53:02.583

5

MIPS

Range - 40

Probably can be golfed much more with x86 or some clever instruction.

Input:

    .text
    .globl main
main:   # Read inputs
    li      $v0, 5      
    syscall         
    move    $t0, $v0

    li      $v0, 5      
    syscall         
    move    $t1, $v0

    li      $v0, 5      
    syscall         
    move    $t2, $v0

Actual program (writes to stack):

loop:   bgtz    $t2, pos
        ble     $t0, $t1, exit  # i <= end
        j       l   
pos:    bge     $t0, $t1, exit  # i >= end
l:      addi    $sp, $sp, -4    
        sw      $t0, 0($sp) # Push $t1
        add     $t0, $t0, $t2
        j       loop

Type - 12 (non-serious)

In MIPS all registers can be used with integer instructions, even the floating point ones.

    .text
    .globl main
main:
    li      $v0, 4
    la      $a0, msg
    syscall

    .data
msg:        .asciiz "Integer (probably)"

qwr

Posted 2014-10-10T17:20:56.510

Reputation: 8 929

4

JavaScript ES 6 - 175 Bytes

I'm counting everything up to the arrow as part of the declaration.

Range 57:

range=(a,b,c)=>{for(r=[i=0];i<Math.ceil((b-a)/c);r[i]=a+i++*c);return r}

Type 45:

type=a=>a.big?'str':a.map?'list':~~a!=a?'float':'int'

Round 54:

round=(a,b)=>(c=Math.pow(10,b),d=a*c,e=d-~~(d),(e<0.5?d-e:d+1-e)/c)

Enumerate 19:

enumerate=a=>a.map((x,y)=>[y,x])

William Barbosa

Posted 2014-10-10T17:20:56.510

Reputation: 3 269

The string type is just str so you can save 3 bytes and comply with the requirements :) – Ingo Bürk – 2014-10-12T19:00:21.003

@IngoBurk Thanks, man :) – William Barbosa – 2014-10-12T21:32:11.423

Some errors: type(1.0) returns int, type([1.3]) returns float. Using ternary instead of || produces shorter code! – Florent – 2014-10-13T09:09:07.140

@Florent Thanks for pointing out, but the 1.0 thing can't be fixed because there's no distinction between integers and floating point numbers in JS :T – William Barbosa – 2014-10-14T11:22:55.663

4

Ruby, 183

range=->a,b,s{r=[a];r<<a while(a+=s)<b;r<<a} # 38 bytes

type=->x{%w[int float str list 1][[1,1.0,'',[]].find_index{|y|x.class===y}||4]} # 74 bytes

round=->n,d{a=10**d;b=n*a;z=b%1;b-=z<0.5?z:(-1+z);b/a} # 48 bytes

enumerate=->l{(0...l.size).zip l} # 23 bytes

I've not counted the names of the lambdas and the = that follows them. Only type handles invalid input. It returns the String "1" when an object with a class other than Integer, Float, String or Array is given. The other functions blow up when, for example, a Symbol is passed where a Numeric is expected. I suspect Python behaves similarly.

britishtea

Posted 2014-10-10T17:20:56.510

Reputation: 1 189

3

Python 3 - 199

Range - 48

def range(s,e,g):
 r=[]
 while[s>e,s<e][g>0]:r+=[s];s+=g
 return r

Enumerate - 32

enumerate=lambda x:[[i,x[i]]for i in range(len(x))]

Or

enumerate=lambda x:zip(range(len(x)),x)

But this doesn't return a list

Round - 29

def round(x,a):
 a=10**-a
 return(x+a/2)//a*a

Type - 90

def type(x):
 x=repr(x)
 if x[0]in"'\"":return str
 if x[0]=="[":return list
 return[int,float]["."in x]

matsjoyce

Posted 2014-10-10T17:20:56.510

Reputation: 1 319

Re. the enumerate, what would the other format be? Keep in mind that other languages can't handle objects in the same way. – Beta Decay – 2014-10-10T19:10:55.697

Just use zip, without the list calls, which results in a zip object of tuples (<zip object at 0x7eff05fee948>, which when iterated over produces (0, 'a') (1, 'b') (2, 'c')) – matsjoyce – 2014-10-10T20:32:49.077

Shouldn't range(0,len(x),1) be the same as range(0,len(x))? – proud haskeller – 2014-10-11T19:36:34.123

1@proudhaskeller He's using his own definition of range which requires the inclusion of the step – Beta Decay – 2014-10-11T22:13:42.460

@BetaDecay Can we use the builtin range, as it could just be range(len(x))? – matsjoyce – 2014-10-12T12:22:25.213

@matsjoyce I suppose so – Beta Decay – 2014-10-12T12:26:32.270

@BetaDecay: Wouldn’t this directly contradict your rules? – Wrzlprmft – 2014-10-12T21:22:39.817

@matsjoyce: round(-1.5,0) should return 1. Also, you do not return 1 for invalid input. – Wrzlprmft – 2014-10-12T21:25:40.810

@Wrzlprmft Also, you do not return 1 for invalid input Neither does the ruby solution, as that would make the length way bigger (catch exceptions, etc.). Also, round(-1.5,0) returns -1.0 for me? – matsjoyce – 2014-10-13T06:48:19.647

@matsjoyce: I noticed, see my comment on the question. round(-1.5,0) should return -2 (rounding away from zero in case of a tie) – I messed up the sign in the last comment.

– Wrzlprmft – 2014-10-13T07:14:27.710

2

Haskell, 86

import Data.Typeable
approx f n=toEnum(fromEnum$10^n*f+0.5)/10^n
getType a=typeOf a
range a b c=[a,a+c..b-c/abs c]
enumerate=zip[0..]

In Haskell there is a type system, so I allowed myself to have a Typeable type-class restriction in getType's type (type is a reserved name in Haskell). to clarify, this is impossible in any other way, as in Haskell you can't cast variables to other types and catch the resulting type exceptions - Haskell simply does not have type errors.

The enumerate functions returns a list of two tuples instead of a list of lists, and I figured that if python tuples weren't immutable they would use them instead.

note that there's already a round function in Haskell so I called the round function approx.

proud haskeller

Posted 2014-10-10T17:20:56.510

Reputation: 5 866

People writing in Python must not use the built-in functions.... If there are similar built-in functions in your language, you must not use them. - You violate this rule with typeOf. – Beta Decay – 2014-10-11T16:04:01.363

@BetaDecay but round is a different function - it rounds to a whole number, and it rounds down on 0.5. it is a different function and thus I can use it. – proud haskeller – 2014-10-11T16:23:50.480

@BetaDecay about typeOf, because Haskell has a strict type system, this is the ONLY way it is possible. you can't just get an Object, try to cast it and catch the exceptions. – proud haskeller – 2014-10-11T16:24:07.870

2Haskell's round would fall under the rule "Floor and ceil functions are not allowed" or the restriction "If there are similar built-in functions in your language, you must not use them", imo. – britishtea – 2014-10-11T17:02:13.610

@britishtea now doesn't use round – proud haskeller – 2014-10-11T18:09:53.227

2

AppleScript, 382

AppleScript is fun to golf but can't compete with other languages. I count the function bodies, but not the declarations of on handler(arg) and end handler.

--range: 82 bytes
on r(i,j,c)
try
set a to{}
repeat while i/c<j/c
set a to a&i
set i to i+c
end
a
on error
1
end
end r

-- type: 131 bytes
on type(x)
try
if x=x as list
"list"
else if x=x as text
"str"
else if x=x as real and"."is in x as text
"float"
else
"int"
end
on error
1
end
end type

-- round: 70 bytes
on round2(x,p)
try
set m to 10^-p
if x<0then set m to-m
(x+m/2)div m*m
on error
1
end
end round2

-- enumerate: 99 bytes
on enumerate(x)
try
set a to{}
repeat with i in r(1,1+count x,1)
set a to a&{{i-1,x's item i}}
end
a
on error
1
end
end enumerate

-- examples: see results in event log
log r(1, 10, 1)
log r(1, 10, 2)
log r(10, 5, -1)
log type(12)
log type(12.0)
log type("12")
log type({13, 45})
log round2(0.5, 0)
log round2(0.2, 0)
log round2(3.14159, 3)
log round2(127.56, -2)
log round2(12.564, 2)
log round2(1457, -2)
log enumerate({1, 2, 3, 4})
log enumerate({"spam", "eggs"})
log enumerate(23)
log round2(56, "hello")
log r("hi", 4, 1)

range

I renamed range to r because my enumerate function calls r.

I use AppleScript errors to detect invalid arguments. If AppleScript raises an error, then the try structure returns 1. Beware that range([1], "10", 1) raises TypeError in Python, but r({1}, "10", 1) is valid here, because AppleScript's operators accept single-item lists and strings as numbers.

The try body is just this:

set a to {}  -- empty list
repeat while i / c < j / c
    set a to a & i  -- append i to list
    set i to i + c
end

The condition needs to be i < j when c is positive, or i > j when c is negative. I golfed it as i/c<j/c, because the division reverses the comparison when c is negative. As a bonus, c being zero raises a division by zero error, so I correctly reject c being zero as invalid.

Beware that set a to a & i is slow because it copies the whole list a every time. The fast way might look like set r to a reference to a, then set end of r to i, but that is not golf.

type

AppleScript's type operator is class of x (or x's class). My own type function uses operator =, because 1 + "1" is 2 but 1 = "1" is false. The try body is this:

if x = (x as list)
    "list"
else if x = (x as text)
    "str"
else if x = (x as real) and "." is in (x as text)
    "float"
else  -- assume x = (x as integer)
    "int"
end

Some arguments are invalid; try calling type(AppleScript) or type(type). Then x as text or x as real raises an error and I return 1. It helps that x as list always works and x as text works with any number.

Because 12 = 12.0 is true, I need another way to tell floats from ints. I observe that 12 as text is "12" but 12.0 as text is "12.0", so I check for "." in string. I have no check for infinities or NaN because trying to compute those would raise errors.

round

I renamed round to round2 because AppleScript has round in its standard additions. The try body is this:

set m to 10^-p
if x < 0 then set m to -m
((x + m / 2) div m) * m

I observe div truncating toward zero. For rounding, I must calculate x + m / 2 when x is positive, or x - m / 2 when x is negative. For golf, I can negate m. In the div m*m part, the negative sign of m cancels itself.

Python's round typically returns a float, but this round2 often returns an integer. AppleScript's operators like to convert floats to integers, perhaps to help 68k Macs with no FPU. (PowerPC Macs emulated a 68LC040 with no FPU.)

enumerate

My enumerate also works with strings. The try body is this:

set a to {}
repeat with i in r(1, 1 + (count x), 1)
    set a to a & {{i - 1, x's item i}}
end
a

I must not use AppleScript's range loop (repeat with i from 1 to count x), but I may call my own range function. I tried to golf away the final a, but I need it when enumerating the empty list or string.

Beware that i is a reference to a number, not the number itself. If I looped in r(0,count x,1) and collected {{i,x's item(i+1)}}, the result might look like {{item 1 of {0, 1}, "spam"}, {item 2 of {0, 1}, "eggs"}}. The operations i-1 and x's item i coerce i to a number.

kernigh

Posted 2014-10-10T17:20:56.510

Reputation: 2 615

2

APL (43+19+18+38=118)

type←{''≡0↑⍵:'str'⋄⍬≢⍴⍵:'list'⋄⍵=⌈⍵:'int'⋄'float'}  ⍝ 43
round←{0::1⋄∆÷⍨⍎0⍕⍵×∆←10*⍺}                          ⍝ 19
enumerate←{0::1⋄(¯1+⍳⍴⍵),¨⊂¨⍵}                       ⍝ 18
range←{0::1⋄0<∆←-⍺⍺:⌽∆+⍵(∆∇∇)⍺⋄⍺<⍵:⍺,⍵∇⍨⍺-∆⋄⍬}    ⍝ 38

I made the argument order consistent with general APL style.

Ungolfed, with explanation.

Test:

      ⍝ range: <start> <step> range <end>
      1 (1 range) 10
1 2 3 4 5 6 7 8 9
      1 (2 range) 10
1 3 5 7 9
      10 (¯1 range) 5
10 9 8 7 6
      ⍝ type: type <obj>. 
      ⍝ 1.0 is considered int, because APL itself does not make the distinction
      type 12
int
      type 12.1
float
      type '12'
str
      type (13 45)
list
      ⍝ APL's native type function: 
      ⎕DR¨ 12 12.0 12.1
83 83 645
      ⍝ round: <digits> round <value>
      0 round 0.5
1
      0 round 0.2
0
      3 round 3.14159
3.142
      ¯1 round 127.56
130
      ¯2 round 127.56
100
      2 round 12.5640
12.56
      ¯2 round 1457
1500
      ⍝ enumerate: enumerate <list>
      enumerate 1 2 3 4
┌───┬───┬───┬───┐
│0 1│1 2│2 3│3 4│
└───┴───┴───┴───┘
      enumerate 'spam' 'eggs'
┌────────┬────────┐
│┌─┬────┐│┌─┬────┐│
││0│spam│││1│eggs││
│└─┴────┘│└─┴────┘│
└────────┴────────┘

marinus

Posted 2014-10-10T17:20:56.510

Reputation: 30 224

Does APL work right to left? I've seen several cases where strings were written backwards... – Beta Decay – 2014-10-13T15:57:00.453

2@BetaDecay: there is no operator precedence, so everything is executed right-to-left, i.e. a F b G c means F(a,G(b,c)). So that also means G must run before F does. If you want the equivalent of G(F(a,b),c), you have to use braces, i.e. (a F b) G c. So that means that if you're writing a function like round, you want to make the precision the left argument and the input the right argument, because you're far more likely to write something like "round all these numbers to three decimal places" than "round this number to zero, one, two, and three decimal places". – marinus – 2014-10-13T17:41:10.733

0

Axiom, 438 445 bytes

The macro used 18 bytes

I==>"int";T==>type

Two macros named I=="int" and T=="type"

the type function 124 bytes

T a==(y:=(tex domainOf a).1;suffix?("Integer()",y)=>I;y="Float()"=>"float";y="String()"=>"str";prefix?("List ",y)=>"list";y)

Function type()[or T] that retrun "int" "float" or "list" it depend of the type of its argument. It can not fail, it would return the right string for the type int, float, list of ???, string, or othewise would return one unknow string different, in Tex language that says its type in Axiom. Example:

(26) -> q:=set [x**2-1, y**2-1, z**2-1];type(q)
   (26)  "Set \left( {{Polynomial \left( {{Integer()}} \right)}} \right)"
                                                             Type: String

the round function 152 bytes

Round(a,c)==(v:=T a;(v~="float"and v~=I)or T c~=I=>%i;a<0=>-Round(-a,c);z:=a*10.^c;x:=truncate(z);w:=0.5+x-z;0<=w and w>10^-digits()=>x/10^c;(x+1)/10^c)

It would return the Round() of the number (it is in count the error of float so we impose bheaviour of it is of the kind Round(0.4999999999999999999, 0) is 0.0 but Round(0.499999999999999999999, 0) is 1.0 and so Round(0.49999999999999999999999999999999, 0) is 1 too). if Round(a,c) find one error it return the complex number %i [the complex costant i]. I don't know how write it without one call one function equivalent to floor (I'm sorry)

the range function 95 bytes

Range(a,b,c)==(T a~=I or T b~=I or T c~=I=>[];[a+c*i for i in 0..(Round((b-a)/c*1.,0)::INT-1)])

It would return the result range as a list of number; if find one error it would return the void list []. It use the above type() and Round(,) function too.

The enumerate function 56 bytes

enumerate a==(T a~="list"=>[];[[i-1,a.i]for i in 1..#a])

It would enumerate the element of the list as in the question; in case of error return [] void list.

Result in the session

(5) -> [[i,j,Round(i,j)] for i in [0.5,0.2,3.14159,127.56,12.5640,1457] for j in [0,0,3,-2,2,-2]]
   (5)
   [[0.5,0.0,1.0], [0.2,0.0,0.0], [3.14159,3.0,3.142], [127.56,- 2.0,100.0],
    [12.564,2.0,12.56], [1457.0,- 2.0,1500.0]]
                                            Type: List List Complex Float
(6) -> Range(1,10,1)
   (6)  [1,2,3,4,5,6,7,8,9]
                                                       Type: List Integer
(7) -> Range(1,10,2)
   (7)  [1,3,5,7,9]
                                                       Type: List Integer
(8) -> Range(10,5,-1)
   (8)  [10,9,8,7,6]
                                                       Type: List Integer
(9) -> type(12)
   (9)  "int"
                                                             Type: String
(10) -> type(12.0)
   (10)  "float"
                                                             Type: String
(11) -> type([13,45])
   (11)  "list"
                                                             Type: String
(12) -> enumerate([1,2,3,4])
   (12)  [[0,1],[1,2],[2,3],[3,4]]
                                                  Type: List List Integer
(13) -> enumerate(["spam","eggs"])
   (13)  [[0,"spam"],[1,"eggs"]]
                                                      Type: List List Any
(14) -> enumerate(23)     -- error for enumerate
   (14)  []
                                                          Type: List None
(15) -> Round(56,"hello") -- error for Round
   (15)  %i
                                                    Type: Complex Integer
(16) -> Range("hi",4,1)   -- error for range
   (16)  []
                                                          Type: List None

In total and in partial too it is a very good question: Thank you very much.

RosLuP

Posted 2014-10-10T17:20:56.510

Reputation: 3 036