g | x | w | all
Bytes Lang Time Link
012Raku Perl 6 rakudo250417T215207Zxrs
004Notepad200829T143729ZTwilight
011Javascript ES6?250329T085150ZSteve Be
040SAKO250329T073053ZAcrimori
008AWK250313T204614Zxrs
245INTERCAL190319T071158ZUnrelate
000Thunno 2 t230607T071841ZThe Thon
012AArch64 machine code221028T175920ZEasyasPi
006ARM Thumb machine code221028T182840ZEasyasPi
010JavaScript Node.js221028T115048Z鳴神裁四点一号
057nroff221019T050741Z鳴神裁四点一号
nanFig220929T172346ZSeggan
001Vyxal221010T131141ZDialFros
008Standard ML220929T161405Zqwr
nan220929T154622Zbigyihsu
002MAWP220929T152535ZDion
011Brainfuck220929T115644ZJoao-3
036M4220929T055213Z鳴神裁四点一号
002MATL190317T210238ZSuever
011Factor220220T000847Zchunes
002J220219T213550Zsinvec
007APOL220216T134844ZGinger
004Julia220216T125740ZMarcMush
048dotcomma201002T095957ZDorian
003Duocentehexaquinquagesimal210416T174625ZMakonede
006vim210413T172112ZRay
nan190317T192114ZBenjamin
002Regex210321T223715Zemanresu
046CSASM v2.2.1.1210321T220906Zabsolute
030Rockstar200924T142325ZShaggy
001Pyth200929T015913ZScott
008Labyrinth200929T005658ZBubbler
013Marbelous200924T163840Zjonatjan
00105AB1E200924T161037ZMakonede
002MathGolf200831T144056ZKevin Cr
004Pip200831T020658ZRazetime
006Scala200829T150229Zuser
002Arn200815T044629ZZippyMag
010Rust200813T184314ZAiden4
014Flurry200813T101539ZBubbler
002Integral200813T095745Zuser9649
002MAWP200813T091421ZRazetime
009Ruby pl200207T012025ZValue In
002Burlesque200207T011015ZDeathInc
003GolfScript200205T163037ZMathgeek
002x8616 machine code190317T213037Z640KB
002APL Dyalog Unicode200203T081341ZBubbler
038naz200203T013346Zsporebal
001Pushy200114T153416ZFlipTack
003GolfScript200114T141040Zuser8505
639BrainFlakcr190926T134553ZDorian
768Scratch 3.0190928T084553Zlyxal
1514Caboose190928T041500Zuser8505
389Mornington Crescent190927T234422ZAlevya
007Perl 5190926T192242ZrpGYNay0
018MarioLANG190926T182023ZDorian
024Clojure190927T042317ZLucky
011Zsh190927T050519Zroblogic
023TSQL190926T184319ZBradC
009Cascade190925T192243ZEdgex42
164Commodore 8bit BASIC CBM/PET190917T125846ZShaun Be
010Triangular190917T125321Zsquid
001Keg190915T142144Zuser8505
013Pepe190513T052736Zu-ndefin
034C190323T212119Zqookie
031C gcc190331T102358ZNatural
004Haskell190324T184201Zunivalen
016Python 3190322T140722ZNathan D
008F#190318T234733ZCiaran_M
011Seed190319T230828Zkungfush
004Haskell190317T200615Zflawr
008LiveScript190318T164737ZVen
009Retina190319T004436ZSara J
001Japt h190318T225912ZShaggy
035R190318T203657ZChthonyx
017Forth gforth190318T201038Zreffu
041Chip z190318T154036ZPhlarx
008C# 8.0190318T161250ZArcanox
017BinaryEncoded Golfical190318T145210ZSuperJed
005Runic Enchantments190318T144748ZDraco18s
001Japt h190318T135322ZOliver
042Turing Machine Code190318T001748ZSuperJed
011IBM/Lotus Notes Formula190318T110932ZElPedro
054Whitespace190318T111047ZKevin Cr
010Excel190318T101909ZWernisch
nanPython 3190317T225429ZMrwerdo
012VBA Excel190318T084212Zremoel
005Emotion190318T074921ZQuantum6
004APL+WIN190318T053024ZGraham
013Bash190317T220202Zbrokenfo
037Twig190318T024723ZIsmael M
010TIBASIC TI84190317T204443Zabsolute
001Japt190318T014817Zdana
011C# Visual C# Interactive Compiler190318T001400Zdana
005Befunge98190318T005135ZJo King
003Scratch 3.0190318T004626ZSilas Re
024Batch190318T000411ZNeil
004Attache190318T001757ZConor O&
011Perl 6190317T234040ZJo King
115C# .NET Core190317T233742ZStackstu
081C# .NET Core190317T233448ZStackstu
013PHP190317T233435Z640KB
001Jelly190317T203047ZNick Ken
391Turing Machine But Way Worse190317T222138ZMilkyWay
008Bash + coreutils190317T222011Zpizzapan
012Befunge93190317T202148ZJPeroute
006Cubix190317T212052ZMickyT
00105AB1E190317T211934ZEmigna
016SmileBASIC190317T211844Z12Me21
002><>190317T211551ZEmigna
016Wolfram Language Mathematica190317T204651Zshrap
011PowerShell190317T202400ZGMills
014Javascript190317T193038ZSuperJed
014Python 3190317T192900ZMilkyWay
007Brainf***190317T192240ZSuperJed

Raku (Perl 6) (rakudo), 12 bytes

{.comb.tail}

Attempt This Online!

Notepad, 9 5 4 keystrokes

Assuming the cursor is at the end of the file.

[LeftArrow][Shift-Home][Backspace]

I know it is not a language, but I'm posting just for fun.

-1 by Steve Bennett

Javascript (ES6?) 11 bytes

s=>s.at(-1)

SAKO, 40 bytes

PODPROGRAM:S(*T)
CALKOWITE:*T
LINIA
WROC

This is suprisingly trivial in SAKO, as last character in a string is always a newline.

Full programme version, 58 bytes

CALKOWITE:*T
BLOK(9):T
1)CZYTAJWIERSZ:T
LINIA
STOP1
KONIEC

Reads from STDIN and prints to STDOUT.

Without newline version, 83 bytes

PODPROGRAM:S(*T)
CALKOWITE:*T,I
I=0
1)I=I+1
GDYT(I)=58:2,INACZEJ1
2)S()=T(I-1)
WROC

This solution is returns second to last character.

AWK, 8 bytes

1,$0=$NF

Attempt This Online!

1,   # always print even if answer is zero
$0=  # set default output
$NF  # last field in line

INTERCAL, 270 258 247 246 245 bytes

DO,1<-#1PLEASECOMEFROM#2DOWRITEIN,1DO.1<-,1SUB#1DO.5<-#1$.1~#256DO.2<-.3DO(1)NEXTPLEASE.2<-!3~#15'$.3~#240PLEASE.2<-!2~#15'$.2~#240PLEASE.2<-!2~#15'$.2~#240DO(1010)NEXTDO,1SUB#1<-.3DOREADOUT,1(1)DO(1002)NEXTDO(1009)NEXTDO.3<-.3~#255(2)DOFORGET#1

Try it online!

-8 thanks to 鳴神裁四点一号 removing DOGIVEUP to terminate by NEXT stack explosion, opening up another -4 changing a PLEASE to DO.

-11 removing some grouping from the bit-reversing expression from hell. It seems that binary operators generally act right-associative in C-INTERCAL, though having no precedence among themselves.

-1 trying something else for bit reversal--definitely expected more savings than that! A more principled approach might be able to do it in two steps unless there's some obvious invariant I'm missing, but I'm too tired to take a stab at that just yet.

-1 thanks again to 鳴神裁四点一号, using a "computed" COME FROM where the computed label just so happens to be a constant. Looks like I wasn't reading enough tips!

Writing this was... interesting. I was thinking I might want to use INTERCAL to INTERCALate, but I'm a bit less sure now.

Ungolfed and commented:

        DO ,1<-#1             PLEASE NOTE We want the input array to only have space for one element, so it will only take one at a time
        DO COME FROM (2)
        DO WRITE IN ,1        PLEASE NOTE If this is the first byte of the input, it'll write its value... but if not, it'll write the
                              previous value minus its value mod 256.
        DO .1<-,1SUB#1
        DO .5<-#1$!1~#256'    PLEASE NOTE .5 is 3 if the input is 256, 2 otherwise
        DO .2<-.3
        DO (1) NEXT

                              PLEASE NOTE If we're here, we've found the end of the input. Now, we need to print it back out... C-INTERCAL's
                              array I/O, in order to determine what it will actually print, subtracts the value it's going to print from the
                              previous one (still mod 256, and with the previous value defaulting to 0), and then reads the bits of the byte
                              backwards. So in order to go from the value we want to display to the value we need to feed into READ OUT, we
                              reverse the bits and then subtract from 256. Rather than select the bits out individually and mingle them all
                              in one expression, I mingle the back and front halves of the byte until it adds up to a reversal.

        DO .2 <- !3~#15' $ !3~#240'
        DO .2 <- !2~#15' $ !2~#240'
        DO .2 <- !2~#15' $ !2~#240'

        DO (1010) NEXT        PLEASE NOTE .1 already has 256 in it, which is very convenient for when you need to subtract .2 from 256.

        DO ,1SUB#1 <- .3      PLEASE NOTE If we just read .3 out, we'd get a Roman numeral instead of the correct output.
        DO READ OUT ,1

        DON'T GIVE UP         PLEASE NOTE Logical end of program. However, if we don't gracefully terminate here, nothing more is output,
                              and the FORGET can't keep up with the NEXTs.

    (1) DO (1002) NEXT        PLEASE NOTE that that line in syslib does 1001 next, which pops .5 entries off the next-stack and returns
                              control flow to the last one, such that if .5 is 2 flow will come back here, but if it's 3 then it'll go back
                              to the line that nexted to this one.

                              Here we add .1 and .2 into .3, then truncate it to a byte before looping back (while managing the next-stack
                              responsibly so the program doesn't disappear into the black lagoon for any input over 79 (?) bytes)

        DO (1009) NEXT
        DO .3<-.3~#255
    (2) DO FORGET #1

Thunno 2 t, 0 bytes

Attempt This Online!

That's right: no bytes. The t flag does all the work.

Or 1 byte flagless:

t

Attempt This Online!

Built-in for last item.

AArch64 machine code, 12 bytes

20 8c c0 28 e3 ff ff 35 c0 03 5f d6

Commented assembly

    .globl lastchar
    // Input: x1: null terminated UTF-32 string
    // Output: w0: last char in string
    // char32_t lastchar(int dummy, const char32_t *str);
lastchar:
.Lloop:
    // load two chars, advance by one char
    // w0 = *x1++; w3 = *x1;
    ldp     w0, w3, [x1], #4
    // loop if w3 was not zero (null terminator)
    cbnz    w3, .Lloop
    // return
    // result is in w0
    ret

This can be called from C using a dummy parameter to put the null terminated UTF-32 string in x1.

char32_t lastchar(int dummy /* x0 */, const char32_t *ptr /* x1 */);

I don't usually do AArch64 because it isn't very compact at 4 bytes per instruction and almost always longer than Thumb, but this particular solution is really elegant even if it is larger than the equivalent Thumb code by 2 bytes (it's solely because of the return instruction being 2 bytes) (Thumb does better with ptr+length though)

ARM Thumb machine code, 6 bytes

01 39 40 5c 70 47

Commented assembly:

    .syntax unified
    .arch armv7-a
    .thumb
    .globl lastchar
    .thumb_func
    // C-callable function
    // Input:
    //  - r0: String of ASCII (not utf-32)
    //  - r1: Length of string
    // Output:
    //  - r0: Char
    // int lastchar(const char *ptr, uint32_t length);
lastchar:
    // It's literally ptr[length - 1]
    // Subtract 1 from the length since ARM can't do [reg, reg, offset]
    subs    r1, #1
    // load ptr[length]
    ldrb    r0, [r0, r1]
    // return in r0
    bx      lr

I mean it is literally return ptr[length - 1], there isn't much to explain. The function is callable using the C convention, using byte string + length (not null-terminated UTF-32 like most of my solutions):

int lastchar(const char *ptr, uint32_t length);

ARM Thumb machine code, 10 bytes

This is the "equivalent Thumb code" I mentioned on my aarch64 answer. It is much less elegant.

01 c9 0b 68 00 2b fb d1 70 47

Commented assembly:

    .syntax unified
    .arch armv7-a
    .thumb
    .globl lastchar
    .thumb_func
    // C-callable function
    // Input:
    //  - r1: Null terminated UTF-32LE string
    // Output:
    //  - r0: Char
    // char32_t lastchar(int dummy, const char32_t *str);
lastchar:
.Lloop:
    // load 1 char, advance pointer 
    ldmia   r1!, {r0}
    // Load next char into temp
    ldr     r3, [r1]
    // compare and loop if r3 wasn't a null terminator
    cmp     r3, #0
    bne     .Lloop
    // return in r0
    bx      lr

This uses the same function signature, taking a null terminated UTF-32 string and a dummy parameter to put str in r1:

char32_t lastchar(int dummy /* r0 */, const char32_t *str /* r1 */); 

In an ideal world, the direct equivalent could be done:

lastchar:
.Lloop:
    ldrd    r0, r3, [r1], #4
    cbnz    r3, .Lloop
    bx      lr

But unfortunately:

JavaScript (Node.js), 10 bytes

Assumes every byte is a letter one of 0 through 9. Is this justified?

s=>s%10+""

Attempt This Online!

nroff, 57 bytes

.de F
.ds X \\$1
.length L \\*X
.substring X \\nL
\\*X
..

Attempt This Online!

Usage

.F "41382239"
.F "e"
.F "what"
.F " a "
.F "b c"

How it works

.de F             \" define macro F
.ds X \\$1        \" store 1st argument to string variable X
                  \" I had to do so because arguments are not in variable, but
                  \" can be obtained via requests only
.length L \\*X    \" store length of X to register L
                  \" no numerical express to do so
.substring X \\nL \" 1-indexed. replace X with L-th to last substring
\\*X              \" content of X
..                \" end of definition

Fig, \$1\log_{256}(96)\approx\$ 0.823 bytes

]

Try it online!

1-byters?? Seriously?? Why have that when you can have 0.823 bytes?? Literally "grab last char of (implicit) input."

Vyxal, 1 byte

t

Try it Online!

Standard ML, 8 bytes

There are two common ways of string processing: char lists and strings. In both cases, the underlying char is an 8 bit value using "extended ASCII".

For char lists:

hd o rev

I'm not sure why List.last isn't top-level, but that works too.

For strings, convert to List and use explode:

hd o rev o explode

Go, 38 bytes

func(s []byte)byte{return s[len(s)-1]}

Attempt This Online!

MAWP, 2 bytes

|;

Try it!

Explanation:

|      take whole input onto stack as ASCII value
 ;     output top of stack

Brainfuck, 11 bytes

,>+[-,>+]<.

Explained:

,> [ ,> ]   get input
  + -  +    sentinels
         <. output last non-NUL byte (NUL doesn't count, doesn't it?)

M4, 36 bytes

define(f,`substr($1,decr(len($1)))')

Attempt This Online!

MATL, 2 bytes

0)

MATL uses 1-based modular indexing so this solution grabs the element in the 0-th position of the input which is the same as the last since the 0 wraps around to the end.

Try it out at MATL Online

Explanation

    % Implicitly grab the input
0   % Push the literal 0 to the stack
)   % Use this zero to grab the character at the end of the string
    % Implicitly display the result

Factor, 11 bytes

[ 1 tail* ]

Try it online!

J, 2 bytes

{:

{: is implicit verb for last element of any array (including strings)

Try it online!

APOL, 7 bytes

g(i -1)

About as simple as possible, just gets the last character of the input string.

Julia, 4 bytes

last

Try it online!

dotcomma, 48 bytes

[[[],],][.[[[,.][.[,]].,][[,].[,]].]][,[,].[,.]]

Try it online!

Because dotcomma is queue-based, you can't easily access the last character. My solution is to reverse the input and then output the first character of it.

Code:

                # reverse the input
[[[],],]        mark the end with 0 0
[.[             while there are characters in input
  [[,.]         put a character on the recursion stack
    [.[,]]      go to reverse section
  .,]           save the character in the reverse section
  [[,].[,]]     go to input section
.]]

[               # get first character and delete all others
  ,[,]          delete 0 and append the next character (last of input) to the end of the queue
  .[,.]         delete everything until we reach a 0
]
                implicitly output the queue

dotcomma (experimental), 17 bytes

[,][[],][.[,.]].,

Try it online!

I marked this "experimental" because the language dotcomma is still very young and I don't know if this is intentional behaviour. If you pass input as a list of strings it reverses each string, so you only need to extract the first letter.

[,]      put first character on recursion stack
[[],]    put 0 (end of queue marker) on queue
[.[,.]]  delete everything from queue
.,       write back character

Duocentehexaquinquagesimal, 3 bytes

t`F

Try it online!

vim, 6 bytes

VGJ$d^

Annotated

VGJ     # join all lines
$       # move cursor to (before) last character
d^      # delete to beginning

Try it online!

Java 11+

Input from STDIN, 71 61 bytes

-10 bytes thanks to OlivierGrégoire

v->{var x=System.in;x.skip(x.available()-1);return x.read();}

Try it online!

Function Argument, 25 bytes

s->s.charAt(s.length()-1)

Regex, 2 bytes

.$

Matches character then end of string.

CSASM v2.2.1.1, 46 bytes

func main:
in ""
push ^1
push ^0
substr
print
ret
end

Commented:

func main:
    ; Get the input
    in ""
    ; Get a substring of the input from (length - 1) to (length - 0)
    push ^1
    push ^0
    substr
    ; Print it
    print
    ret
end

Rockstar, 30 bytes

listen to S
cut S
say S at S-1

Try it here (Code will need to be pasted in)

Or 51 bytes if we need to be able to handle newlines in the input:

listen to S
while S
listen to S

cut S
say S at S-1

Pyth, 1 byte

e

Try it online!

Labyrinth, 8 bytes

,);.@
"(

Try it online!

,)("  Loop until EOF (-1): push a char input, increment, then decrement
;.@   On EOF, discard top, print the last char, and halt

Marbelous, 13 bytes

@0
00
]]..
@0

Marbelous is a language based on marble machines

interpretor

05AB1E, 1 byte

θ

Try it online!

   # (implicit) push STDIN to stack
θ  # push last character of top of stack
   # (implicit) output top of stack to STDOUT

MathGolf, 2 bytes

┤Þ

Try it online.

Or alternatively:

Try it online.

Explanation:

┤   # Pop the left character of the (implicit) input-string loose to the stack
 Þ  # Only leave the top item of the stack, and discard everything else
    # (implicitly output the entire stack joined together)

b   # Push -1
 §  # Get the -1'th character of the (implicit) input-string
    # (0-based modulair similar as Python, so will index into the last character)
    # (implicitly output the entire stack joined together)

Pip, 4 bytes

a@-1

@RVa also works, and is the same size.

Try it online!

Scala, 6 bytes

_.last

Try it online!

Not much to say here - it's just a function that takes a string (or really any iterable) and outputs its last element.

Arn, 2 bytes

:}

Pretty simple, the suffix :} gets the last element of an array (implicit casting)

Rust, 25 16 10 bytes

|s|s.pop()

Try it on the Rust Playground!

An anonymous function that takes in a mutable String and outputs the char at the end of the string. Minus a lot of bytes, thanks to madlaina

Flurry, 14 bytes

([]{(){}{}}{})

Run example

$ echo -n "?" | ./flurry -bnb -c "([]{(){}{}}{})"
?
$ echo -n "Hello world" | ./flurry -bnb -c "([]{(){}{}}{})"
d

-bnb flag means "print stack as chars, print nothing for return value, and take stdin as chars".

If the challenge were asking for "the last value from an integer array", I would use return value output and write 2 byte solution {} (pop the stack and return it). But since character I/O is required and the only way to output a char is via the stack, I had to manually empty the stack.

How it works

(
 []     Stack height as Church numeral; Given 2 arguments `f` `x`,
          a Church numeral `n` acts as "apply `f` `n` times to `x`"
 {      Define f, with its argument pushed to the stack:
  ()      K; Given two arguments, ignore the second
  {}      Pop; the argument
  {}      Pop; pop an extra item from the stack (ignored by K)
 }      End definition of f: Return its argument unchanged,
          popping and discarding an item from the stack
 {}     Pop an item (last char)
        At this point, the stack is empty and the value is the last char
)     Push the result of the above

Integral, 2 Bytes

Vn

Try it!

Explanation

V  Reverse the input
 n Head

MAWP, 2 bytes

|;

Outputs top of stack.

Try it!

Ruby -pl, 9 bytes

Similar to the Perl solution, but chop doesn't return the last character in Ruby. (It instead returns the rest of the string without the last character.)

$_=$_[-1]

Try it online!

Burlesque, 2 bytes

[~

Try it online!

If it needs to be pretty formatted [~Q

[~ # Last char

GolfScript, 3 bytes

Though there was already a Golfscript 3 byte solution, I figured I'd throw in the more general-purpose one.

)\;

Where ( is the front-uncon function (Golfscript treats strings as char arrays), \ swaps the string and char positions, and ; deletes the string, leaving only the last char.

x86-16 machine code, 2 bytes

As @CodyGray correctly points out, taking input as a string and output to a register removes the bulk of the standalone program version.

Input string is in SI, length in CX and output character is in AL:

F3 AC  REPZ LODSB      ; start at memory location pointer in SI, put next value in AL,
                       ; loop CX number of times. The last char will be in AL when done.

Or 4 bytes as a "Pascal string" (length is prepended to beginning of string):

AC     LODSB           ; first byte is string length
91     XCHG AX, CX     ; move length to CX for loop 
F3 AC  REPZ LODSB      ; start at memory location pointer in SI, put next value in AL,
                       ; loop CX number of times. The last char will be in AL when done.

Or 5 bytes as a "C string" (zero/null terminated), input in DI:

F2 AE     REPNZ SCASB     ; scan for value in AL (0), end when found and advance DI
8A 45 FE  MOV AL, [DI-2]  ; DI is now two bytes ahead of last, put value of DI-2 into AL

x86-16 machine code, IBM PC DOS, 12 11 10 bytes

Or as complete program as IBM PC DOS executable. Input is from command line, output is to console.

B3 80   MOV  BL, 80H            ; BX to DOS PSP at 80H 
8A 07   MOV  AL, BYTE PTR[BX]   ; get command line tail length 
D7      XLAT                    ; AL = [BX+AL] 
B4 0E   MOV  AH, 0EH            ; PC BIOS write to screen function  
CD 10   INT  10H                ; display  
C3      RET                     ; exit to DOS

Output:

enter image description here

APL (Dyalog Unicode), 2 bytesSBCS

⊢/

Try it online!

The code taken literally means to "reduce by right argument function". It works like the following (basically like foldr1 (flip const) in Haskell):

  ⊢/ 'abcd'
→ 'a' ⊢ 'b' ⊢ 'c' ⊢ 'd'
→ 'a' ⊢ 'b' ⊢ 'd'
→ 'a' ⊢ 'd'
→ 'd'

This is an idiom for taking last element from a vector (or taking last element from each row of a multi-dimensional array).

naz, 38 bytes

2a2x1v1x1f1r3x1v2e2x2v1f0x1x2f2v1o0x1f

Works for any input string terminated with the control character STX (U+0002).

Explanation (with 0x commands removed)

2a2x1v             # Set variable 1 equal to 2
1x1f1r3x1v2e2x2v1f # Function 1
                   # Read a byte of input
                   # Jump to function 2 if it equals variable 1
                   # Otherwise, store it in variable 2,
                   # then jump back to the start of the function
1x2f2v1o           # Function 2
                   # Load variable 2 into the register and output it
1f                 # Call function 1

Pushy, 1 byte

'

Try it online!

Print the top of stack as a character!

GolfScript, 3 bytes

The GolfScript = yields a decimal. That's pretty weird ... However, (luckily enough,) GolfScript supports slicing over a string, which allows me to slice the last item of the string.

-1>

Try it online!

Explanation

-1  # The last item
  > # Choose everything in the string
    # after the last item, including the last item
    # this (obviously) yields the last item

Brain-Flak-cr, (6 bytes code + 3 bytes command line) = 9 bytes

({}<>)

Try it online!

Code:

The command line argument "-cr" means "use ASCII input and output" and "reverse the stack", so when you pop a value, the last byte of the input is popped, and when you push a value, it is pushed to the end.

 {}     pop a character
(    )  and push it
   <>   on the other stack
        implicitly output the current stack

Scratch 3.0, 7 blocks/68 bytes

enter image description here

or, as scratchblocks syntax

when gf clicked
ask()and wait
say(letter(length of(answer))of(answer

Try it on scratch

Did I mention this was done 100% on mobile? Because it was really hard making this, but I think it was worth it.

Caboose, 1514 bytes

Caboose hates me, because it does. There isn't any convenient string-indexing instruction in Caboose!

var a=input();print(a.endsWith(' ')and' 'or a.endsWith('!')and'!'or a.endsWith('"')and'"'or a.endsWith('#')and'#'or a.endsWith('$')and'$'or a.endsWith('%')and'%'or a.endsWith('&')and'&'or a.endsWith("'")and"'"or a.endsWith('(')and'('or a.endsWith(')')and')'or a.endsWith('*')and'*'or a.endsWith('+')and'+'or a.endsWith(',')and','or a.endsWith('-')and'-'or a.endsWith('.')and'.'or a.endsWith('/')and'/'or a.endsWith('0')and'0'or a.endsWith('1')and'1'or a.endsWith('2')and'2'or a.endsWith('3')and'3'or a.endsWith('4')and'4'or a.endsWith('5')and'5'or a.endsWith('6')and'6'or a.endsWith('7')and'7'or a.endsWith('8')and'8'or a.endsWith('9')and'9'or a.endsWith(':')and':'or a.endsWith(';')and';'or a.endsWith('<')and'<'or a.endsWith('=')and'='or a.endsWith('>')and'>'or a.endsWith('?')and'?'or a.endsWith('@')and'@'or a.endsWith('A')and'A'or a.endsWith('B')and'B'or a.endsWith('C')and'C'or a.endsWith('D')and'D'or a.endsWith('E')and'E'or a.endsWith('F')and'F'or a.endsWith('G')and'G'or a.endsWith('H')and'H'or a.endsWith('I')and'I'or a.endsWith('J')and'J'or a.endsWith('K')and'K'or a.endsWith('L')and'L'or a.endsWith('M')and'M'or a.endsWith('N')and'N'or a.endsWith('O')and'O'or a.endsWith('P')and'P'or a.endsWith('Q')and'Q'or a.endsWith('R')and'R'or a.endsWith('S')and'S'or a.endsWith('T')and'T'or a.endsWith('U')and'U'or a.endsWith('V')and'V'or a.endsWith('W')and'W'or a.endsWith('X')and'X'or a.endsWith('Y')and'Y'or a.endsWith('Z')and'Z'or a.endsWith('[')and'['or a.endsWith('\\')and'\\'or a.endsWith(']')and']'or'~');

If I add more constants, then Caboose will say that there are too many constants in the chunk. Fortunately it passes all test cases given. Basically it (tries to) check the last character against all characters in printable ASCII.

TIO

Mornington Crescent, 389 Bytes

Even a task as simple as this presents an interesting optimisation challenge when riding the London Underground.

Take Northern Line to Bank
Take Circle Line to Bank
Take Central Line to Mile End
Take Central Line to Holborn
Take Piccadilly Line to Heathrow Terminals 1, 2, 3
Take Piccadilly Line to Acton Town
Take District Line to Acton Town
Take District Line to Parsons Green
Take District Line to Mile End
Take Central Line to Bank
Take Circle Line to Bank
Take Northern Line to Mornington Crescent

Try it online!

Visiting Mile End station allows you to take a substring from the end of the input - but to chop just 1 character, you need to generate the integer 1 somehow. Rather than doing any arithmetic, the fastest method turns out to be to parse it from the station name "Heathrow Terminals 1, 2, 3".

To bypass that, an alternate strategy for this challenge would be to reverse the input, read the character code for the now first byte, and then turn that back into a char to output - but this approach takes 12 bytes longer. (Although there are fewer trips needed, so the tickets would be cheaper.)

Perl 5, 7 bytes

$_=chop

This must be executed using the -pe flags.

Example

$ echo -n "abcd" | perl -pe '$_=chop'
d

Explanation

The -p flag wraps code inside a block that appears as: while (<>) { ... ; print } whereas the '...' would include the code provided. The entire script would expand to:

while (<>) { $_ = chop ; print }

What I did here was set the context variable $_ to the return value of chop, which returns the last character of a string. Shortly after, print with no statements on its own will display the previously assigned context variable.

MarioLANG, 18 bytes

>,
"+
)[
!<(-
#==.

Try it online!

code:

>    go right
,    read input
+    increment it (because EOF = -1)
[    ignore the next command, if current cell = 0
<    go to the left
!    stop moving (Mario is now standing on the elevator (#), 
     which rides up to the elevator end (")
)    go to the next memory cell
     Mario is now at the starting position (>) and runs another round 
     until the end of input

else (if he ignored the "<" instruction)
(    go one memory cell back (to the last inputted byte)
-    decrement it, so it becomes the original value again
.    print it

Clojure, 32 bytes 24 bytes

(print(last(read-line)))
(print             ;; prints output
  (last            ;; get last character of input
    (read-line)))  ;; read input

Try it online!

Zsh, 11 bytes

try it online!!

<<<${1: -1}

clone of the bash answer, 2 bytes shorter

T-SQL, 23 bytes

SELECT RIGHT(v,1)FROM i

Didn't see a SQL solution yet.

Input is via a pre-existing table \$i\$ with varchar field \$v\$, per our IO rules.

Cascade, 9 bytes

?a|,
;.]^

Pretty happy with this, as it is only 3 bytes longer than my cat program

Expanded

   ?
  ^;.
 | |a
 ] |
a ,|

This essentially just loops through pushing input characters into the a stack until EOF is reached. Then it outputs the item at the top of the a stack using .a.

Try it online!

Commodore 8-bit BASIC (CBM/PET, VIC-20, C64/TheC64Mini, C128, C16/+4) - byte count later

 0inputa$:iflen(a$)thenprintright$(a$,1)

Simplified (without the sanity check):

 0inputa$:?right$(a$,1)

There is a small limitation in that Commodore 8-bit BASIC the maximum length of a string is 255 characters, so any entry above that will cause an error.

Triangular, 10 bytes

(#~p../)?<

Try it online!

Pretty straight-forward; reads characters until it gets a null read, then prints the top of the stack.

Ungolfed:

   ( 
  # ~ 
 p . . 
/ ) ? <
--------------------------------------------
(            Set a point to jump back to
 ~.<         Read a character, change directions ("." is a no-op)
    ?)/      If ToS <= 0, skip next instruction and change directions; otherwise, jump back to "("
       p#    Pop the top value from the stack (the null input), then pop again and print that value

Keg, 1 byte

This is the exact thing that Keg was built for.

,

Explanation

# Push implicit string input
,# Output the last pushed character
# There is no implicit output since something was outputted

TIO

Pepe, 13 bytes

REEeREEEeReEe

Try it online! Disable "Separated by" check box below the input text box.

Explanation:

REEe  # Input as string (stack R)
REEEe # Goto last char (stack R)
ReEe  # Output char (stack R)

C, 36 35 34 bytes

x(char*v){printf(v+strlen(v)-1);}

Really simple stuff here. Nothing to ungolf either.

Saved one byte thanks to ceilingcat
Fixed the answer and saved another byte thanks to ASCII-only

C (gcc), 31 bytes

f(int*s){gets(s),printf("%s");}

Try it online!

Haskell, 4 bytes

last

Functions are allowed, right?

Also with IO (18 bytes):

main=interact$last

Python 3, 16 bytes

This is a pretty basic answer, but I think that it is the lowest Python 3 can go...

x=lambda a:a[-1]

TIO

F#, 14 8 bytes

Seq.last

-6 bytes thanks to aloisdg.

Strings are treated as sequences in F#, so you can use the Seq.last function to get the last character in it.

Seed, 11 bytes

5 370394306

Try it online!

The resulting Befunge-98 program ~2j@, was stolen borrowed from Jo King here, so credit to them for that.

Haskell, 9 4 bytes

last

Try it online!

LiveScript, 8 bytes

(.[*-1])

Explanation:

(.[*-1])
(.[*-1]) # "BIOP": operator section à la Haskell
 .[   ]  # Index into the implicit argument
   *-1   # In [], "*" refers to the length

Retina, 10 9 bytes

(.|¶)*
$1

Try it online!

Japt -h, 1 byte

Can handle input as a string, integer or character/digit array.

s

Try it

R, 35 bytes

Takes the input, splits it in to a list, outputs the last element of the list.

tail(strsplit(scan(,''),'')[[1]],1)

Try it online!

Forth (gforth), 17 bytes

: f 1- + 1 type ;

Try it online!

Explanation

Adds string-length - 1 to the string address and then prints a string of length 1 starting at that address.

Code Explanation

: f        \ start a new word definition
  1-       \ subtract 1 from string length
  +        \ add result to string address
  1 type   \ print string of length 1 starting at the new address
;          \ end word definition

Chip -z, 41 bytes

S
>vvvvvv~t
ABCDEFG
|Zz||Zz
zbcZzfg
a  de

Try it online!

Assumes that either the byte string does not contain zero (\0), or that it designates the end of the string.


Alternate solution (45 bytes):

azABZbczCDZdezEFZfgzG
S-^^----^^----^^----^~t

Try it online!

C# 8.0, 8 bytes

Requires .NET Core 3.0, which is in beta. This currently crashes the CLR due to a bug, but once the bug is fixed, this will run as expected and fulfill the challenge requirements.

s=>s[^1]

C# 8.0, Runs without crashing at time of writing, 22 bytes

s=>s.ToCharArray()[^1]

C# 8.0, Full Program, 78 bytes

using C=System.Console;class A{static void Main(){C.Write(C.ReadLine()[^1]);}}

Binary-Encoded Golfical, 17 bytes

Hex-dump of binary encoded file:

00 60 02 1b 1a 08 01 14
16 14 24 1d 0a 01 14 18
14

Original image:

enter image description here

Magnified 45x with colors labeled:

enter image description here

The original image (the tiny one, not the magnified version) can be run using the interpreter normally. The binary encoded file (of which a hexdump is included above) can either be transpiled back to the image version with the Encoder program included in the github repo, or run directly using the interpreter by adding the -x flag.

Runic Enchantments, 5 bytes

i1Z%@

Try it online!

Note that input handling in Runic has implicit conversion and breaks on spaces. \ denotes a literal space (works on newlines too) and numerical values are never strings.

Japt -h, 1 byte

U

Run it online

Turing Machine Code, 72 42 bytes

Assumes an input with no empty cells (spaces). Thanks to ASCII-only for saving 30 bytes.

0 * * r 1
1 * * l 2
1 _ _ l halt
2 * _ r 0

Old version in 72 bytes:

0 * * r 0
0 _ * l 1
1 * * l 2
2 * _ l 2
2 _ _ r 3
3 _ _ r 3
3 * * * halt

Try it online.

IBM/Lotus Notes Formula, 11 bytes

@Right(i;1)

Computed field formula taking its input from editable field i

enter image description here

Whitespace, 54 bytes

[N
S S N
_Create_Label_LOOP][S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   S _Read_STDIN_as_character][T   T   T   _Retrieve_input][S N
S _Duplicate][S S S T   S T S N
_Push_10][T S S T   _Subtract][N
T   S S N
_If_0_Jump_to_Label_PRINT][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT][S N
N
_Discard_top][T N
S S _Print_as_character]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Since Whitespace can only take input as integer or character, we must add a trailing character to indicate we're done with the input-string after reading it character by character, for which I've used a newline.

Try it online (with raw spaces, tabs and new-lines only).

Example run: input = A2#

Command    Explanation                   Stack                Heap    STDIN STDOUT STDERR

NSSN       Create Label_LOOP             []
 SSSN      Push 0                        [0]
 SNS       Duplicate top (0)             [0,0]
 TNTS      Read STDIN as character       [0]                  {0:65}  A
 TTT       Retrieve at heap address (0)  [65]                 {0:65}
 SNS       Duplicate top (65)            [65,65]              {0:65}
 SSSTSTSN  Push 10                       [65,65,10]           {0:65}
 TSST      Subtract top two (65-10)      [65,55]              {0:65}
 NTSSN     If 0: Jump to Label_PRINT     [65]                 {0:65}
 NSNN      Jump to Label_LOOP            [65]                 {0:65}
 
 SSSN      Push 0                        [65,0]
 SNS       Duplicate top (0)             [65,0,0]
 TNTS      Read STDIN as character       [65,0]               {0:50}  2
 TTT       Retrieve at heap address (0)  [65,50]              {0:50}
 SNS       Duplicate top (50)            [65,50,50]           {0:50}
 SSSTSTSN  Push 10                       [65,50,50,10]        {0:50}
 TSST      Subtract top two (50-10)      [65,50,40]           {0:50}
 NTSSN     If 0: Jump to Label_PRINT     [65,50]              {0:50}
 NSNN      Jump to Label_LOOP            [65,50]              {0:50}

 SSSN      Push 0                        [65,50,0]
 SNS       Duplicate top (0)             [65,50,0,0]
 TNTS      Read STDIN as character       [65,50,0]            {0:35}  #
 TTT       Retrieve at heap address (0)  [65,50,35]           {0:35}
 SNS       Duplicate top (35)            [65,50,35,35]        {0:35}
 SSSTSTSN  Push 10                       [65,50,35,35,10]     {0:35}
 TSST      Subtract top two (35-10)      [65,50,35,25]        {0:35}
 NTSSN     If 0: Jump to Label_PRINT     [65,50,35]           {0:35}
 NSNN      Jump to Label_LOOP            [65,50,35]           {0:35}

 SSSN      Push 0                        [65,50,35,0]
 SNS       Duplicate top (0)             [65,50,35,0,0]
 TNTS      Read STDIN as character       [65,50,35,0]         {0:10}  \n
 TTT       Retrieve at heap address (0)  [65,50,35,10]        {0:10}
 SNS       Duplicate top (10)            [65,50,35,10,10]     {0:10}
 SSSTSTSN  Push 10                       [65,50,35,10,10,10]  {0:10}
 TSST      Subtract top two (10-10)      [65,50,35,10,0]      {0:10}
 NTSSN     If 0: Jump to Label_PRINT     [65,50,35,10]        {0:10}

NSSSN      Create Label_PRINT            [65,50,35,10]        {0:10}
 SNN       Discard top                   [65,50,35]           {0:10}
 TNSS      Print as character to STDOUT  [65,50]              {0:10}        #
                                                              {0:10}               error

Stops with the error: Exit not defined.

Excel, 10 bytes

Pretty much equivalent to @remoel's VBA answer:

=RIGHT(A1)

Python 3, 11 18 34 Bytes

import sys;print(sys.argv[-1][-1])

Usage via running the program as a python script on the command line. Input is provided as the last argument to the program.

Try it online!

VBA (Excel), 14 12 bytes

using Immediate Window and Cell A1 as input

Thanks @tsh

?[RIGHT(A1)] or ?Right([A1],1)

Emotion, 5 bytes

😶👉😃😨👿

Explanation

😶 Push a copy of the first stack value.
👉 Push the length of the first stack value interpreted as a string.
😃 Push literal 1
😨 Push the difference of the second and first stack values.
👿 Push the character of the second stack value at the index of the top stack value.

Try it online!

APL+WIN, 4 bytes

¯1↑⎕

Prompt for input string and select last byte.

Bash, 13 bytes

echo ${1: -1}

string is passed as argument.

Try it online !

Twig, 37 bytes

This just uses a simple "extract 1 char from the end and print it" aproach.

{%macro a(a)%}{{a[-1:1]}}{%endmacro%}

It was really easy to do, and test, but was fun!


To use it, you have to put it on a .twig file and import it:

{% import 'a.twig' as a %}
{{ a.a("string") }} {# should display "g" #}

You can test it on https://twigfiddle.com/aa19wd (testcases included)

TI-BASIC (TI-84), 10 bytes

sub(Ans,length(Ans),1

Gets the last character in the input string.
Input is in Ans.
Output is in Ans and is automatically printed out.

Japt, 1 byte

Ì

Try it online!

-1 byte thanks to Quintec!

C# (Visual C# Interactive Compiler), 11 bytes

x=>x.Last()

Try it online!

Befunge-98, 5 bytes

~2j@,

Try it online!

Explanation:

~           Take input
 2j         Skip next two instructions
~           Repeat until EOF, where it reflects
   @,       Print the last character and exit

Scratch 3.0, scratchblocks3 syntax

As a function, 61 bytes

define l
ask[]and wait
say(letter(length of(answer))of(answer

As a full program, 68 bytes

when gf clicked
ask[]and wait
say(letter(length of(answer))of(answer

Try both online

Batch, 24 bytes

@set s=%1
@echo %s:~-1%

Takes input as a command-line argument. Note that arguments can't include special characters or spaces, but you can fake arguments with spaces in this case by preceding it with a ", which results in a single argument that begins with ", however there is no easy solution for arguments that include special characters. Batch can't easily read "all of stdin". To read up to but not including the first newline itself would however be a byte shorter:

@set/ps=
@echo %s:~-1%

Edit: A version that handles arbitrary characters in a (quoted) argument for 92 bytes:

@set s="%~1"
@set "s=%s:~-2,1%
@if "%s%"=="" (echo ^")else for %%s in ("%s%")do @echo %%~s

Explanation: The first line makes a copy of the argument in a variable and ensures that it is quoted. The second argument then takes the second last character (because the quote is now the last character). However, if that was also a quote then this results in an empty variable, so we need to special-case that and output a (quoted) quote. Otherwise, we still need to quote the character in case it is a special character as echoing "%s%" will echo the quotes and echoing %s% will actually interpret special characters, so the variable needs to be quoted to allow it to be parsed but then immediately unquoted so it can be printed. This is achieved using the for command. 86 bytes to read up to but not including the first newline from stdin while supporting special characters:

@set/ps=
@set "s=%s:~-1%
@if "%s%"=="" (echo ^")else for %%s in ("%s%")do @echo %%~s

Attache, 4 bytes

Last

Try it online! (If the input could be a list of characters, &/S could work.)

Alternatives

5 bytes: `@&-1

8 bytes: &/S@List

10 bytes: `@«_,-1»

10 bytes: Fold!Right

10 bytes: `@<~_,-1~>

10 bytes: `^^&:Right

10 bytes: {Right^^_}

11 bytes: Get«_,-1»

11 bytes: Get<~_,-1~>

12 bytes: `@«_,#_-1»

12 bytes: `@<~_,#_-1~>

13 bytes: Get«_,#_-1»

13 bytes: Get<~_,#_-1~>

Perl 6, 11 bytes

*.comb[*-1]

Try it online!

Anonymous Whatever lambda that takes a string, splits it into characters, and returns the last one.

C# (.NET Core), 115 bytes, console input

using C=System.Console;class M{static void Main(string[] a){int c=0,d;while((d=C.Read())>-1)c=d;C.Write((char)c);}}

Try it online!

This feels kinda janky, but it does work. Interestingly, I can't save any bytes with a for loop as the code stands.

C# (.NET Core), 81 bytes, command-line input

class M{static void Main(string[] a){System.Console.Write(a[0][a[0].Length-1]);}}

Try it online!

If you run this from an actual command line, you will need to wrap your string in quotes if it contains spaces.

PHP, 13 bytes

<?=$argn[-1];

Try it online!

Run with php -nF input is STDIN. Example:

$ echo 29845812674|php -nF lost.php

Jelly, 1 byte

Try it online!

Not the most difficult challenge in Jelly...

Note this accepts the input as a string; if the input could be interpreted otherwise (e.g. a number, a list), then it the argument will need to be quoted (e.g. "123456" or "[123,197]"). Alternatively this can be seen as a link that takes a byte array and returns the last member of that array, in accordance with PPCG standard rules.

Thanks to @MilkyWay90 and @ბიმო for pointing this out.

Turing Machine But Way Worse, 391 bytes

1 0 1 1 0 0 0
0 0 0 1 1 0 0
1 1 1 1 0 0 0
0 1 0 1 2 0 0
1 2 1 1 0 0 0
0 2 0 1 3 0 0
1 3 1 1 0 0 0
0 3 0 1 4 0 0
1 4 1 1 0 0 0
0 4 0 1 5 0 0
1 5 1 1 0 0 0
0 5 0 1 6 0 0
1 6 1 1 0 0 0
0 6 0 1 7 0 0
1 7 1 1 0 0 0
0 7 0 1 8 0 0
1 8 1 1 0 0 0
0 8 0 0 9 0 0
0 9 0 0 a 0 0
0 a 0 0 b 0 0
0 b 0 0 c 0 0
0 c 0 0 d 0 0
0 d 0 0 e 0 0
0 e 0 0 f 0 0
0 f 0 0 h 0 0
0 h 0 0 g 0 0
0 g 0 0 0 1 1
1 g 1 0 0 1 1

Try it online!

EXPLANATION

Detect eight zero bits (which will occur at the end of the input, since TMBWW uses an infinite tape of bits.)
1 1 1 1 0 0 0
0 1 0 1 2 0 0
1 2 1 1 0 0 0
0 2 0 1 3 0 0
1 3 1 1 0 0 0
0 3 0 1 4 0 0
1 4 1 1 0 0 0
0 4 0 1 5 0 0
1 5 1 1 0 0 0
0 5 0 1 6 0 0
1 6 1 1 0 0 0
0 6 0 1 7 0 0
1 7 1 1 0 0 0
0 7 0 1 8 0 0
1 8 1 1 0 0 0
0 8 0 0 9 0 0

-------------

When eight 0 bits are detected, move back to the final byte of the input and print it out while halting the program.
0 9 0 0 a 0 0
0 a 0 0 b 0 0
0 b 0 0 c 0 0
0 c 0 0 d 0 0
0 d 0 0 e 0 0
0 e 0 0 f 0 0
0 f 0 0 h 0 0
0 h 0 0 g 0 0
0 g 0 0 0 1 1
1 g 1 0 0 1 1

Bash + coreutils, 8 bytes

tail -c1

Input is from stdin, output is to stdout.

Befunge-93, 12 15 bytes

:1+_p1-,@>~#

Try it online!

Thanks to @Jo King for golfing off 3 bytes.

Alternate 15 byte version that is less messy:

~:1+#v!_
  @,$<

Taking strings as input in Befunge isn't the easiest. If there were a single command to take in multiple characters, it would be as simple as reading the string, popping/printing the top character, and exiting.

Cubix, 6 bytes

pA/@po

Try it online!

  p
A / @ p
  o

Watch it run

05AB1E, 1 byte

¤

Try it online!

θ or ` would also work.

SmileBASIC, 16 bytes

INPUT S$?POP(S$)

><>, 2 bytes

Using command line args

o;

Try it online!

><>, 11 bytes

Using stdin

\~o;
/?(0:i

Try it online!

Wolfram Language (Mathematica), 16 bytes

#~StringTake~-1&

Try it online!

PowerShell, 11 bytes

"$args"[-1]

Try it online!

Javascript, 14 bytes

a=>a.slice(-1)

Python 3, 14 bytes

lambda x:x[-1]

Try it online!

Brainf***, 7 bytes

,[>,]<.