27
\$\begingroup\$

In the C standard library, header names end with a .h suffix:

stdio.h

In C++, those header names are available in an alternative form, with a c prefix instead:

cstdio

Write a function that converts the first form into the second. You can do the conversion in-place, or leave the original string intact and return a new string. Whatever feelds natural in your language of choice.

The code must be compiled/interpreted without errors. Compiler warnings are acceptable.

Here is your baseline C solution. It has 70 characters and generates a warning about strlen:

void f(char*h){int i=strlen(h);h[--i]=0;while(--i)h[i]=h[i-1];*h='c';}

The shortest solution (measured in number of characters) wins.

Update: If your language of choice does not support functions, whole programs are also acceptable.

Update: As suggested by FUZxxl, here is a complete list of the header files in the C standard library:

assert.h
ctype.h
errno.h
float.h
limits.h
locale.h
math.h
setjmp.h
signal.h
stdarg.h
stddef.h
stdio.h
stdlib.h
string.h
time.h

Specifically, there are no header names with multiple dots in them.

\$\endgroup\$

51 Answers 51

37
\$\begingroup\$

80386 machine code, 13 bytes

Hexdump of the code:

b0 63 86 01 41 3c 2e 75 f9 c6 01 00 c3

Source code (can be compiled by Visual Studio):

__declspec(naked) void __fastcall conv(char s[])
{
    _asm {
        mov al, 'c';            // b0 63
    myloop:
        xchg al, [ecx];         // 86 01
        inc ecx;                // 41
        cmp al, '.';            // 3c 2e
        jne myloop;             // 75 f9
        mov byte ptr [ecx], 0;  // c6 01 00
        ret;                    // c3
    }
}

It converts the string in-place. The code is so simple, it doesn't need to save and restore registers (using only al and ecx, which the fastcall convention allows to clobber).

\$\endgroup\$
  • \$\begingroup\$ Nice, this takes me back :) \$\endgroup\$ – fredoverflow Feb 12 '15 at 20:24
  • \$\begingroup\$ Definitely one of the cooler solutions! But the source code isn't really 13 bytes, only the compiled form of it (that I think few of us would want to write in a hex editor). \$\endgroup\$ – Per Lundberg Feb 13 '15 at 19:57
  • 3
    \$\begingroup\$ Give him his win. Byte = character is a perfectly reasonable interpretation here. \$\endgroup\$ – Joshua Feb 13 '15 at 20:38
  • 7
    \$\begingroup\$ @PerLundberg I see the source code in this case as being the "how it works" expanded/commented explanation that a lot of people include in their ultra-compact languages. For such a small program it could very well have been hand-written. :) \$\endgroup\$ – fluffy Feb 13 '15 at 21:13
  • \$\begingroup\$ @fluffy Fair point. And yeah, the number of people that could write the binary code by heart is certainly >0, even though I don't know anyone that geeky myself. ;) \$\endgroup\$ – Per Lundberg Feb 14 '15 at 19:35
14
\$\begingroup\$

Python: 19 characters

lambda s:'c'+s[:-2]
\$\endgroup\$
14
\$\begingroup\$

CJam, 6 bytes

'clW(<

This is a full program which reads the string via STDIN

Explanation:

'c               "Put character c on stack";
  l              "Read a line from STDIN";
   W             "W is a predefined variable with value -1";
    (            "Decrease the value by 1";
     <           "Remove last 2 characters from the string on stack, the input argument";

Try it online here

\$\endgroup\$
  • \$\begingroup\$ Isn't -2 just as good as W(? \$\endgroup\$ – Esolanging Fruit May 6 '18 at 22:29
12
\$\begingroup\$

Java 8 — 25 characters

h->"c"+h.replace(".h","")
\$\endgroup\$
11
\$\begingroup\$

brainfuck - 25 23 bytes

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

If your language of choice does not support functions, whole programs are also acceptable.

This is a whole program that takes input from STDIN.

,[>,]      get all bytes of input
<-----.    subtract 5 from last byte (always "h"; "h" minus 5 = "c") and print result
<,         set second last byte to 0 by abusing comma
<[<]>      go to first byte
[.>]       print byte and move right until hitting 0
\$\endgroup\$
  • \$\begingroup\$ Wouldn't this step off the left edge of the tape upon [<] \$\endgroup\$ – feersum Feb 13 '15 at 18:13
  • \$\begingroup\$ @feersum If your interpreter allows you to step off the left edge, yes. Every one I've ever used loops the tape. \$\endgroup\$ – undergroundmonorail Feb 13 '15 at 22:54
  • 2
    \$\begingroup\$ @feersum If you'd like to try it but your interpreter does allow you to fall off, you can fix it with a > at the beginning. \$\endgroup\$ – undergroundmonorail Feb 14 '15 at 16:34
10
\$\begingroup\$

Haskell — 23 characters

('c':).takeWhile(/='.')

Haskell — 16 characters, as suggested by nimi

('c':).init.init
\$\endgroup\$
  • 2
    \$\begingroup\$ Dropping the last 2 characters with init.init instead of taking all up to the first . saves a few bytes. \$\endgroup\$ – nimi Feb 12 '15 at 19:59
  • \$\begingroup\$ @nimi That is an awesome suggestion! \$\endgroup\$ – fredoverflow Feb 12 '15 at 20:01
10
\$\begingroup\$

C, 38

See on Ideone

f(s,o){snprintf(o,strlen(s),"c%s",s);}

s is a pointer to the input string, and o is where the output should be written to.

I found a way to abuse snprintf. The output string conveniently happens to be one character shorter than the input, and the maximum length of the string written by snprintf is 1 less than the n argument, so it cuts off the .h. Note: this technique will not work with Microsoft's implementation because it does the wrong thing and fails to null-terminate the string.

\$\endgroup\$
8
\$\begingroup\$

Windows Batch file 11

@echo c%~n1

The first parameter passed in is %1. The ~n modifier returns just the filename without extension.

If it's acceptable to echo the expanded command to the screen as well, then the initial @ could be removed.

\$\endgroup\$
8
\$\begingroup\$

TIS Node Type T21 Architecture - 85 bytes

This answer is just for fun; the language came into existence after this challenge was written and I therefore cannot win with it. (Not that I was going to.)

Okay, I had a little fun with this one. I probably should just call the language "TIS-100", but why break character? :D

TIS-100 is a game about programming a computer with a totally unique and bizarre architecture. I wrote a custom puzzle for this challenge, which allows me to take input and check output against a known-correct "string". Unfortunately, there's no way to handle strings or characters, so this program simply uses the ASCII value of each character for input and output.

If you'd like to see it in action, you can use this emulator, or just watch me run it in the actual game here. Note that in the video, the final line of the first node is D:MOV UP NIL. After finishing the video, I realized I could golf that down to D:ADD UP. Functionally there's no difference, because the value of ACC is immediately overwritten anyway.

This is the string I used for my byte count:

MOV 99 ANY
MOV -46 ACC
ADD UP
JEZ D
ADD ACC ANY
JRO -5
D:ADD UP
MOV UP ANY
MOV UP ANY

That's the text of each non-empty node, seperated by newlines (effectively adding 1 byte for each node used beyond the first, mirroring our rule about code in multiple files).

\$\endgroup\$
7
\$\begingroup\$

Dyalog APL (8 characters)

'c',¯2↓⊢

This solution is exactly the same as the J solution I submitted but uses one character less due to being one character less than }..

\$\endgroup\$
7
\$\begingroup\$

J (9 characters)

'c',_2}.]
  • |y is the magnitude of y (also called absolute value)
  • x }. y drops |x items from y; items are dropped from the front if x is positive, from the end if x is negative.
  • x , y appends x and y.
  • 'c' , _2 }. y does the transformation you want; in tacit notation this can be expressed as 'c' , _2 }. ].
\$\endgroup\$
7
\$\begingroup\$

Ostrich 0.6.0, 8 characters

););"c\+

) is the "right uncons" operator. When applied to a string, it turns, for example, `foo` into `fo` `o`. ; is used to pop the extra character off, and this is done again.

Then, "c is pushed. This is simply a shorthand for `c`.

\+ swaps the top two stack elements and concatenates them.

\$\endgroup\$
  • \$\begingroup\$ Was this language created by you? \$\endgroup\$ – Ismael Miguel Feb 13 '15 at 11:17
  • \$\begingroup\$ @IsmaelMiguel Yes. (See the main Github repo.) \$\endgroup\$ – Doorknob Feb 13 '15 at 12:37
  • \$\begingroup\$ I though so. I already checked it, therefore thinking about it. There is no reference on that language anywhere. Only here. So, I assumed it was made by you. For a 14 years old guy, you went really far on programming. +1000 for that! \$\endgroup\$ – Ismael Miguel Feb 13 '15 at 12:44
  • \$\begingroup\$ @IsmaelMiguel Whoops, sorry, should have told you that I'm KeyboardFire on Github. Thanks! \$\endgroup\$ – Doorknob Feb 13 '15 at 12:46
  • \$\begingroup\$ You don't need to. It's almost implied. I'm ismael-miguel (very original, check github.com/ismael-miguel). I have nothing interesting and useful there, but you may check it. But I'm interested on your language. The only complete thing is the UIntArray class for php (github.com/ismael-miguel/php-uintarray if you are interested). \$\endgroup\$ – Ismael Miguel Feb 13 '15 at 12:48
7
\$\begingroup\$

piet (9x11 = 99 8X11=88)

v2

another try (2x37 = 74)

enter image description here

Hard to make it much smaller since it needs to generate a 99 ('c') and a 46('.'), and that takes space in piet.

\$\endgroup\$
  • 1
    \$\begingroup\$ Piet's never measured in characters, only codels, so you don't need to mention the 0 chars bit :) Also that's a lot of white \$\endgroup\$ – Sp3000 Feb 12 '15 at 23:08
  • \$\begingroup\$ trying to compress, but it is a bit difficult. Having trouble getting it to terminate if I remove yet another row or column. \$\endgroup\$ – captncraig Feb 12 '15 at 23:11
  • \$\begingroup\$ This is a bit of cheating, but I like it. This is like using /dev/null as your source-code. \$\endgroup\$ – Ismael Miguel Feb 13 '15 at 12:46
  • 2
    \$\begingroup\$ According to META (meta.codegolf.stackexchange.com/questions/4782/…), your program isn't required to finish. As long as it does it's task, your program can run forever. Read the first answer to the question. \$\endgroup\$ – Ismael Miguel Feb 13 '15 at 15:38
6
\$\begingroup\$

F# - 39 37 31

31 - Because typeinference in F# rocks!

fun s->("c"+s).Replace(".h","")

37

fun(s:string)->"c"+s.Replace(".h","")

39

fun(s:string)->"c"+s.Remove(s.Length-2)
\$\endgroup\$
  • \$\begingroup\$ Doesn't work for a header named foo.hoo.h. \$\endgroup\$ – FUZxxl Feb 13 '15 at 15:49
  • 3
    \$\begingroup\$ @FUZxxl There are no such headers in the C standard library. \$\endgroup\$ – fredoverflow Feb 13 '15 at 16:25
  • \$\begingroup\$ @FredOverflow You might want to specify the set of names on which the transformation has to work. Right now your question is worded in a way that might lead people to assume that this kind of input must work correctly. \$\endgroup\$ – FUZxxl Feb 13 '15 at 16:56
  • \$\begingroup\$ @FUZxxl I have updated the question accordingly. \$\endgroup\$ – fredoverflow Feb 13 '15 at 17:51
6
\$\begingroup\$

gema, 6

*.h=c*

(Gema is an obscure macro language.)

\$\endgroup\$
4
\$\begingroup\$

Bash, 18

f()(echo c${1%.*})

Output:

$ f stdio.h
cstdio
$ 
\$\endgroup\$
4
\$\begingroup\$

GNU sed -r, 14

sed doesn't really have any concept of functions, so here is a complete sed program instead:

s/(.*)../c\1/

Output

$ sed -r 's/(.*)../c\1/' <<< stdio.h
cstdio
$ 

The -r has been included in the score as one extra character.

\$\endgroup\$
  • \$\begingroup\$ This solution is invalid: It should probably be s/\(.*\)\.h/c\1/ instead. \$\endgroup\$ – FUZxxl Feb 12 '15 at 20:32
  • \$\begingroup\$ @FUZxxl - I'm assuming -r is passed to sed. As per usual code-golf I need to count that as an extra point. \$\endgroup\$ – Digital Trauma Feb 12 '15 at 20:43
  • \$\begingroup\$ @DigitalTraume Notice that -r is not a standard option and not available outside of GNU sed. You might want to change the language name to GNU sed to reflect that. \$\endgroup\$ – FUZxxl Feb 12 '15 at 20:51
  • \$\begingroup\$ @FUZxxl Yes. Done. \$\endgroup\$ – Digital Trauma Feb 12 '15 at 20:52
  • 2
    \$\begingroup\$ \.h can be shortened to .. \$\endgroup\$ – Steven Taschuk Feb 14 '15 at 19:37
3
\$\begingroup\$

Prelude, 31 characters

Since full program submissions are apparently acceptable, here is a program that reads the C-style header from STDIN and prints the C++-style header to STDOUT:

99+9+(?)###(#
9(1-)       ^)(!)

This requires a standard-compliant interpreter which prints output as character codes. If you're using the Python interpreter you'll need to set NUMERIC_OUTPUT = False.

It also requires that there's no trailing newline on STDIN.

Explanation

In Prelude all lines are executed in parallel, one column at a time. Each line has its own stack, initialised to an infinite amount of 0s.

99+9+
9(1-)

This is the shortest I could come up with to get a 99 onto the top stack (the character code of c). First I add up 18 on the top stack and push a 9 onto the bottom stack. The bottom then counts down to 0 in a loop, while the top stack adds more 9s up. This adds up to 99 on the top stack, and the bottom stack is left with 0s again. Note that all of +9+ is part of the loop, so there are actually two addition operations per iteration, but that's not an issue, thanks to the infinite supply of 0s underneath.

Now (?) reads STDIN, one character at a time and pushes onto the top stack. The loop terminates at the end of the input, when ? pushes a zero. ### gets rid of that zero, the h and the .. Now the next loop pops numbers from the top stack while copying them to the bottom stack. This essentially reverses the stack. Note that the opening and closing parentheses are on different lines - this is not an issue, because the vertical position of the ) is irrelevant in Prelude, but it saves me a byte on the first line.

Lastly, (!) prints all the characters until the stack is empty.

\$\endgroup\$
3
\$\begingroup\$

Pyth, 7 characters

L+\cPPb

Explanation:

L         def y(b):return
 +\c                      "c" +
    PPb                         b[:-1][:-1]

Try this:

L+\cPPb
y"stdio.h

on the online Pyth Compiler/Executor


If full programs were allowed:

Pyth, 6 characters

+\cPPQ
\$\endgroup\$
  • \$\begingroup\$ I have never seen Pyth. Would you be so kind and explain the code? :) \$\endgroup\$ – fredoverflow Feb 12 '15 at 19:51
  • 1
    \$\begingroup\$ @FredOverflow See codegolf.stackexchange.com/q/40039/18487 \$\endgroup\$ – Rainbolt Feb 12 '15 at 19:52
  • \$\begingroup\$ I believe you can use PPb instead of <b_2 \$\endgroup\$ – FryAmTheEggman Feb 12 '15 at 21:10
  • \$\begingroup\$ @FryAmTheEggman Thanks. \$\endgroup\$ – isaacg Feb 12 '15 at 21:17
  • \$\begingroup\$ It seems like full programs are allowed, so you can get to 6. \$\endgroup\$ – FryAmTheEggman Feb 13 '15 at 18:41
3
\$\begingroup\$

C++14, 41 characters

[](auto&s){s="c"+s.substr(0,s.size()-2);}

Inspired by this other answer. I made it a separate answer because here I use a feature that is new in c++14, generic lambda.

See it in action here.

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

T-SQL — 58 characters

CREATE PROC Q(@ VARCHAR(MAX))AS
SELECT'c'+LEFT(@,LEN(@)-2)

Run as EXEC Q (your string here)

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

Perl — 20 characters

sub{c.pop=~s/..$//r}

Note how c is a bareword and as such this requires a lack of use strict. This must be used as an expression, not a statement.

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

Marbelous, 24

@063
-Z//
3W<C+Z
]]!!
@0

Takes input through STDIN, outputs to STDOUT.

This works by checking each byte with . (0x46). As 0x46 cannot fit inside a single base-36 digit, we subtract 35 (Z) before comparing, and add it back before outputting.

Each marble is duplicated by 3W (three-way duplicator, but the left side is discarded off the side of the board). The marble sent downwards fetches the next byte from STDIN. The marble to the right is checked to ., then either outputted, or sent to !!, which terminates the program.

The program starts by passing c (0x63) through, which will be output to STDOUT.

Try it online here. Libraries must be enabled, cylindrical boards must be disabled.

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

C, 64

Mildly shorter than the c reference:

f(char*h){char*d=strstr(h,".");memmove(h+1,h,d++-h);*d=0;*h=99;}

Probably more golfing to be done with this.


C, 48 (libc hack)

f(char*h){strcpy(h+1,h);*strstr(h,".")=0;*h=99;}

The strcpy manpage explicitly states "The strings may not overlap". However I found that the libc I am using appears to be coded safely to handle this correctly all the same. This is GNU C Library (Ubuntu EGLIBC 2.19-0ubuntu6.4) on Ubuntu 14.04.

\$\endgroup\$
  • \$\begingroup\$ Is omitting the return type of a function legal in C89? \$\endgroup\$ – fredoverflow Feb 12 '15 at 20:59
  • 1
    \$\begingroup\$ @FredOverflow. Yes - gcc compiles this just fine with -std=c89. codegolf.stackexchange.com/a/2204/11259 \$\endgroup\$ – Digital Trauma Feb 12 '15 at 21:06
  • \$\begingroup\$ @FredOverflow Yes. The return type defaults to int. \$\endgroup\$ – FUZxxl Feb 12 '15 at 21:08
  • \$\begingroup\$ The man page just reiterates the Standard - compiling this with VC++ (VS2012) gives "cstdii" for "stdio.h". Didn't check ICC/Sun/clang, but your 64-char version says "why?" - it's about as short as it can (legally) be in C. \$\endgroup\$ – frasnian Feb 16 '15 at 0:18
2
\$\begingroup\$

JavaScript (ES6) 20

Can't believe ES6 was still missing

s=>'c'+s.slice(0,-2)
\$\endgroup\$
2
\$\begingroup\$

Perl, 15 (14 + -p)

s/(.*)\.h/c$1/
\$\endgroup\$
2
\$\begingroup\$

mk, 34 characters

mk(1) is the Plan 9 replacement for make. Just for fun, this mkfile converts C header names into C++ header names:

c%:Q:
    :

%.h:Q: c%
    echo $prereq

There is a single tab before : and echo. Use like this:

% mk stdio.h
cstdio
\$\endgroup\$
1
\$\begingroup\$

CoffeeScript - 16

(x)->"c"+x[..-3]
\$\endgroup\$
1
\$\begingroup\$

TI-BASIC 83/84, 15

"c"+sub(Ans,1,length(Ans)-2
\$\endgroup\$
1
\$\begingroup\$

R, 33

function(x)sub("(.+)..","c\\1",x)

This function uses regular expressions.

Example usage:

> (function(x)sub("(.+)..","c\\1",x))("stdio.h")
[1] "cstdio"
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.