21
\$\begingroup\$

Your challenge is to find the file extension of a provided filename:

hi.txt -> txt or .txt
carrot.meme -> meme or .meme
lol (undefined behavior)
what..is..this..file -> file or .file
.bashrc -> bashrc or .bashrc
T00M@n3KaPZ.h0wC[]h -> h0wC[]h or .h0wC[]h
agent.000 -> 000 or .000

You must get the text from the last . or after the last . to the end of the string. The first capturing group match of the regular expression /\.([^.]+)$/ works, and so does splitting the input on .s and returning the last one.

The file name will always contain at least one ., but it may contain multiple .. (see examples)

The input will always match ^[.a-zA-Z0-9^!\[\]{}@$%+=]+$.

\$\endgroup\$
7
  • 19
    \$\begingroup\$ Please consider using the Sandbox in the future to get feedback on your challenges before posting them to the main site. \$\endgroup\$ – user45941 May 16 '17 at 20:45
  • 1
    \$\begingroup\$ codegolf.meta.stackexchange.com/a/12432/59376 - Got this idea from your challenge. \$\endgroup\$ – Magic Octopus Urn May 16 '17 at 21:51
  • \$\begingroup\$ @carusocomputing nice challenge! \$\endgroup\$ – user58826 May 17 '17 at 0:06
  • 2
    \$\begingroup\$ why the negative votes? Is this challenge "exceedingly trivial" or so ? \$\endgroup\$ – Abel Tom May 17 '17 at 5:09
  • \$\begingroup\$ @AbelTom edit history would suggest downvotes were for the lack of specifications in the first draft of this question. \$\endgroup\$ – Patrick Roberts May 17 '17 at 5:12

96 Answers 96

2
\$\begingroup\$

JavaScript, 21 bytes

x=>x.split('.').pop()

Explanation:

This code takes x.txt and turns it into a array. The last element of the array is the file type. This code uses the pop function to remove the last element. In the process, the pop function returns the last element.

\$\endgroup\$
3
  • \$\begingroup\$ +Dennis, I have turned it into a arrow function. Does this comply with the rules? \$\endgroup\$ – Aspect Mar 13 '18 at 0:15
  • \$\begingroup\$ Yes, it is fine now. :) By the way, StackExchange uses @ to ping people, not +. \$\endgroup\$ – Dennis Mar 13 '18 at 0:18
  • 2
    \$\begingroup\$ Save 2 bytes with x=>x.split`.`.pop(). \$\endgroup\$ – Grant Miller Mar 14 '18 at 2:02
2
\$\begingroup\$

Python 3, 46 bytes

-8 bytes thanks to Wheat Wizard and Scrooble

import sys
print(sys.argv[1].split('.')[-1])

EDIT: I fixed the code, and the filename is a command-line argument

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Welcome to the site! This doesn't appear to work, so you should either fix, or delete this answer. \$\endgroup\$ – Dude coinheringaahing Mar 11 '18 at 17:55
  • \$\begingroup\$ This works for 54 \$\endgroup\$ – NoOneIsHere Mar 11 '18 at 17:57
  • \$\begingroup\$ To get the last item of a list you can use -1 as the index instead of len(a)-1. You could also probably change your input format to reduce the number of bytes. \$\endgroup\$ – Wheat Wizard Mar 11 '18 at 18:21
  • \$\begingroup\$ Adding to WW's suggestion: if you use -1 rather than len(a)-1, you no longer need the assignment and can save quite a few bytes. \$\endgroup\$ – Khuldraeseth na'Barya Mar 11 '18 at 21:12
2
\$\begingroup\$

Kotlin, 17 bytes

split(".").last()

Beautified

split(".").last()

Test

data class Test(val input: String, val output: String)

val test = listOf(
        Test("hi.txt", "txt"),
        Test("carrot.meme", "meme"),
        Test("what..is..this..file", "file"),
        Test(".bashrc", "bashrc"),
        Test("T00M@n3KaPZ.h0wC[]h", "h0wC[]h"),
        Test("agent.000", "000")
)

fun String.f() =
split(".").last()

fun main(args: Array<String>) {
    for ((i, o) in test) {
        if (o != i.f()) {
            throw AssertionError()
        }
    }
}

TIO

TryItOnline

\$\endgroup\$
2
\$\begingroup\$

FORTRAN 90, 87 bytes

CHARACTER(99)F,L
READ*,F;DO I=1,LEN(F)
IF(F(I:I)=='.')L=F(I:LEN(F))
ENDDO
PRINT*,L
END

A shorter version in FORTRAN 90.


FORTRAN 77, 137 bytes

      PROGRAMC;IMPLICITCHARACTER*99(F)
      READ*,F;DOI=LEN(F),1,-1;IF(F(I:I).EQ.'.')THEN
      PRINT*,F(I:LEN(F));EXIT;ENDIF;ENDDO;END

There is no space in PROGRAM C, nor in IMPLICIT CHARACTER. It works (!) in gfortran, but I'm not sure it works in others compilers. The program takes input from stdin and outputs the extension with the period. The total length of the file name is limited by 99.

\$\endgroup\$
2
\$\begingroup\$

V, 4 bytes

òdt.

Try it online!

Recursively delete everything up to, but not including the next .

\$\endgroup\$
2
\$\begingroup\$

C++, 73 bytes

I'm a bit surprised that no one tried C++, since it's an easy one :

#include<string>
auto e=[](std::string s){return s.substr(s.rfind(46));};

And the code to test ( may have to iostream, initializer_list, and exception ) :

std::initializer_list<std::string> test{
    "hi.txt", // .txt
    "carrot.meme", // .meme
    "lol", // invalid string position
    "what..is..this..file", // .file
    ".bashrc", // .bashrc
    "T00M@n3KaPZ.h0wC[]h", // .h0wC[]h
    "agent.000" // .000
};

for (const auto& a : test) {
    try {
        std::cout << e(a) << '\n';
    }
    catch (std::out_of_range& r) {
        std::cout << "out of range exception : " << r.what() << '\n';
    }
}

And, as you may expect, like compilers, if there's undefined behavior, there's no undefined behavior. If there's no file extension, the function will throw a std::out_of_range exception, as said in cppreference

\$\endgroup\$
2
\$\begingroup\$

SmileBASIC, 45 bytes

INPUT S$@L
E$=POP(S$)+E$ON"."==E$[0]GOTO@L?E$

Outputs extension with the period.

\$\endgroup\$
2
\$\begingroup\$

Turing Machine But Way Worse, 1315 1287 bytes

0 0 0 1 1 0 0
1 0 1 1 8 0 0
0 1 0 1 2 0 0
1 1 1 1 9 0 0
0 2 0 1 3 0 0
1 2 1 1 a 0 0
0 3 0 1 4 0 0
1 3 1 1 b 0 0
0 4 0 1 5 0 0
1 4 1 1 c 0 0
0 5 0 1 6 0 0
1 5 1 1 d 0 0
0 6 0 1 7 0 0
1 6 1 1 e 0 0
0 7 0 1 f 0 0
1 7 1 1 0 0 0
0 8 0 1 9 0 0
1 8 1 1 9 0 0
0 9 0 1 a 0 0
1 9 1 1 a 0 0
0 a 0 1 b 0 0
1 a 1 1 b 0 0
0 b 0 1 c 0 0
1 b 1 1 c 0 0
0 c 0 1 d 0 0
1 c 1 1 d 0 0
0 d 0 1 e 0 0
1 d 1 1 e 0 0
0 e 0 1 0 0 0
1 e 1 1 0 0 0
0 f 0 0 g 0 0
1 f 1 0 g 0 0
0 g 0 0 h 0 0
1 g 1 0 p 0 0
0 h 0 0 q 0 0
1 h 1 0 i 0 0
0 i 0 0 r 0 0
1 i 1 0 j 0 0
0 j 0 0 s 0 0
1 j 1 0 k 0 0
0 k 0 0 l 0 0
1 k 1 0 t 0 0
0 l 0 0 u 0 0
1 l 1 0 m 0 0
0 m 0 0 n 0 0
1 m 1 0 v 0 0
0 n 0 0 o 0 0
1 n 1 0 g 0 0
0 p 0 0 q 0 0
1 p 1 0 q 0 0
0 q 0 0 r 0 0
1 q 1 0 r 0 0
0 r 0 0 s 0 0
1 r 1 0 s 0 0
0 s 0 0 t 0 0
1 s 1 0 t 0 0
0 t 0 0 u 0 0
1 t 1 0 u 0 0
0 u 0 0 f 0 0
1 u 1 0 f 0 0
0 o 0 1 w 0 0
1 o 1 1 w 0 0
0 w 0 1 x 0 0
1 w 1 1 E 0 0
0 x 0 1 y 0 0
1 x 1 1 F 0 0
0 y 0 1 z 0 0
1 y 1 1 G 0 0
0 z 0 1 A 0 0
1 z 1 1 H 0 0
0 A 0 1 B 0 0
1 A 1 1 I 0 0
0 B 0 1 C 0 0
1 B 1 1 J 0 0
0 C 0 1 D 0 0
1 C 1 1 K 0 0
0 D 0 1 D 0 1
1 D 1 1 w 1 0
0 E 0 1 F 0 0
1 E 1 1 F 0 0
0 F 0 1 G 0 0
1 F 1 1 G 0 0
0 G 0 1 H 0 0
1 G 1 1 H 0 0
0 H 0 1 I 0 0
1 H 1 1 I 0 0
0 I 0 1 J 0 0
1 I 1 1 J 0 0
0 J 0 1 K 0 0
1 J 1 1 K 0 0
0 K 0 1 w 1 0
1 K 1 1 w 1 0

Try it online!

Wow, this is big.

\$\endgroup\$
1
  • \$\begingroup\$ Wow this is incredible! \$\endgroup\$ – MilkyWay90 Aug 10 '19 at 5:47
2
\$\begingroup\$

Befunge-98 (FBBI), 50 bytes

{v
 >~:a`!#v_
--2*86:$<:u-10_v#
02-u0}>:#,_@   >00

Try it online!

Puts string onto stack, then iterates through it in reverse, putting each new character onto new stack. Once a . is encountered, discard original stack and output new stack in 0gnirts format.

\$\endgroup\$
2
\$\begingroup\$

Forth (gforth), 45 bytes

: f begin 1 -1 d+ s" ."search 0= until type ;

Try it online!

Code Explanation

: f              \ start a new word definition
  begin          \ start an indefinite loop
    1 -1 d+      \ remove the first character from the string
    s" ."search  \ find the length and starting address of the first substring that starts with '.'
    0=           \ check if '.' was found in the string
  until          \ end the loop if not
  type           \ output the result
;                \ end the word definition
 
\$\endgroup\$
2
\$\begingroup\$

brainfuck, 45 bytes

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

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Setanta, 66 34 bytes

gniomh(s){toradh roinn@s(".")[-1]}

Try it here!

\$\endgroup\$
2
\$\begingroup\$

Arn, 6 bytes

Ê^!⁺╔d

Try it!

Explained

Unpacked: :!".":}

    _ Variable initialized to STDIN; implied
  :! Split on
    "." String containing a period
:} Tail
\$\endgroup\$
2
+100
\$\begingroup\$

APL (Dyalog Unicode), 10 bytes (SBCS)

⊃∘⌽'.'∘≠⊆⊢

-7 bytes after Bubbler's suggestion.

Try it online!

APL (Dyalog Unicode), 17 bytes (SBCS)

⊃⌽'.'(1↓¨,⊂⍨⊣=,)⍞

Explanation

⊃⌽'.'(1↓¨,⊂⍨⊣=,)⍞
                ⍞ string input
            ⊣=,)  get characters, evaluate if they are equal to the left arg '.'
         ,⊂⍨      enclose each part after a dot
  '.'(1↓¨         drop each dot in the strings
 ⌽                reverse the split string array
⊃                 take the first value

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ Including the dot is allowed (so you don't need 1↓¨), but then, you can use ≠⊆⊢ idiom to split the words at dots, excluding dots. \$\endgroup\$ – Bubbler Aug 28 '20 at 7:11
  • \$\begingroup\$ Then the tacit ⊃∘⌽'.'∘≠⊆⊢ is one byte shorter than full program ⊃⌽'.'(≠⊆⊢)⍞. \$\endgroup\$ – Bubbler Aug 28 '20 at 7:20
  • \$\begingroup\$ interesting. I'll try it out. How do it get it to work on TIO? \$\endgroup\$ – Razetime Aug 28 '20 at 7:26
  • \$\begingroup\$ No different from other function submissions. \$\endgroup\$ – Bubbler Aug 28 '20 at 7:35
  • 1
    \$\begingroup\$ Or equally long: ⊃∘⌽⎕NPARTS \$\endgroup\$ – Adám Jun 12 at 22:17
2
\$\begingroup\$

Python3 (32 bytes)

f=input()
print(f[f.rfind('.'):])

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to the site. You might like to include a link to Try it online! in your answer. TIO is widely used here because it's quite handy: not only does it let other people try out your code, it also creates pre-formatted CGCC submissions for you. \$\endgroup\$ – Dingus Aug 29 '20 at 9:32
2
\$\begingroup\$

8086 Assembly (NASM) + DOS, 262 bytes source, 50 bytes assembled

I'm pretty new to assembly, but I thought I'd give this a try. This is a full DOS program, not just a snippet.

section .bss
b resb 256
org 256
section .text
mov byte[b],254
mov ah,10
mov dx,b
int 33
mov bh,0
mov bl,[b+1]
add bx,b+2
mov bp,bx
l:sub bx,1
cmp byte[bx],46
jne l
mov byte[bx],10
p:mov ah,2
mov dl,[bx]
int 33
add bx,1
cmp bx,bp
jb p
int 32

Essentially, it reads a line of text into a buffer, seeks the end, then seeks backwards until it reaches a .. Then it just prints the rest of the string from that point on. I wasn't able to use DOS's built-in print function, though, since that uses $ as the end-of-string character, which the prompt says is a valid character for the extension itself.

Here is the hexdump of the assembled binary:

00000000  c6 06 34 01 fe 88 e4 ba  34 01 cd 21 b7 00 8a 1e
00000010  35 01 81 c3 36 01 89 dd  83 eb 01 80 3f 2e 75 f8
00000020  c6 07 0a b4 02 8a 17 cd  21 83 c3 01 39 eb 72 f3
00000030  cd 20
\$\endgroup\$
2
\$\begingroup\$

33 v1.0, 13 bytes

The behaviour of the y operator was changed in v1.1, so this program no longer works

Gets the file name passed as an argument and prints the extension (without leading '.') to standard output.

1bt'.'ywmcbtp

Explanation:

1b            (Gets the second item in argv, the filename input)
  t'.'y       (Splits that by '.')
       wmcb   (Gets the last element in the list)
           tp (Prints to standard output)
\$\endgroup\$
1
\$\begingroup\$

Python 2, 25 bytes

lambda s:s.split('.')[-1]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Brain-Flak, 84 bytes

Includes +2 for -rc

(()){{}([((((()()()){}())()){}{}){}]({}<>)<>)({()(<{}>)}{})}{}{{}}<>{}{({}<>)<>}<>

Try it online!

# Push 1 to start the loop
(())

# Start loop
{{}

  # If TOS == 46 i.e. '.'
  ([((((()()()){}())()){}{}){}]({}<>)<>)({()(<{}>)}{})
  # ^------------------------^ ^-------^ 
  #           This is 46         Also, copy TOS to other stack

# End loop after the first '.'
}{}

# Delete everything from this stack
{{}}

# Delete the '.' that got copied
<>{}

# Copy everything back to reverse it to the correct order
{({}<>)<>}<>
\$\endgroup\$
1
\$\begingroup\$

Japt, 6 5 bytes

q'. o

Try it online!

Explanation

 q'. o
Uq'. o
Uq'.    # Split the input at "."
     o # Return the last item
\$\endgroup\$
1
  • \$\begingroup\$ When you only need to return the last item of an array, you can use o in place of gJ. (Learned that trick from @obarakon a while back) \$\endgroup\$ – ETHproductions May 16 '17 at 23:38
1
\$\begingroup\$

jq, 15 14 characters

(11 10 characters code + 4 characters command line options.)

./"."|last

Sample run:

bash-4.4$ jq -Rr './"."|last' <<< 'what..is..this..file'
file

On-line test

\$\endgroup\$
1
\$\begingroup\$

Octave, 24 bytes

@(x)strsplit(x,'.'){end}

Creates an anonymous function named ans which can accept a string as input

Online Demo

\$\endgroup\$
1
\$\begingroup\$

Pyth, 5 bytes

ecz\.

try it here

\$\endgroup\$
1
\$\begingroup\$

Charcoal, 6 4 bytes

-2 bytes thanks to Erik the Outgolfer

⊟⪪S.

Try it online!

Explanation

⊟      Pop
  ⪪ .  Split on "."
   S  Next input as string
       Implicit print of value
\$\endgroup\$
1
  • \$\begingroup\$ Can't you use ⊟x instead of §x±¹? \$\endgroup\$ – Erik the Outgolfer May 17 '17 at 13:13
1
\$\begingroup\$

REXX 53

parse value reverse(arg(1)) with e "." 
say reverse(e)
\$\endgroup\$
1
\$\begingroup\$

C#, 35 bytes

s=>s.Substring(s.LastIndexOf("."));

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Haskell, 32 30 29 bytes

-1 byte thanks to Laikoni

r=reverse
r.fst.span(/='.').r

self-explanatory

\$\endgroup\$
1
  • 1
    \$\begingroup\$ takeWhile can be shortened to fst.span. \$\endgroup\$ – Laikoni May 17 '17 at 16:17
1
\$\begingroup\$

Cheddar, 16 bytes

@.sub(/.*\./,"")

simple regex solution. Alternative solution using split:

@.split('.')[-1]
\$\endgroup\$
1
\$\begingroup\$

Ruby, 16 bytes

->s{s[/[^.]+$/]}

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ 15 bytes with -p \$\endgroup\$ – vrintle Dec 7 '20 at 12:05
  • \$\begingroup\$ or, 14 bytes if "..." are acceptable :p \$\endgroup\$ – vrintle Dec 7 '20 at 12:08
1
\$\begingroup\$

K (oK), 6 bytes

Solution:

*|"."\

Try it online!

Examples:

*|"."\"whats.up.txt"
"txt"
  *|"."\"T00M@n3KaPZ.h0wC[]h"
"h0wC[]h"

Explanation:

Split \ the input on ".", reverse | this list, and then take the first * one. K is interpreted right-to-left:

*|"."\ / the solution
  "."\ / "." split (\),
 |     / reverse
*      / first
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy