[Question]
  [
**Goal:** Write a program or function which prints an input string in a sinusoidal shape.
### The ASCII sinusoid
Here is one period of the sinusoid:
```
         .......                                 
      ...       ...                              
    ..             ..                            
   .                 .                           
  .                   .                          
 .                     .                         
.                       .                       .
                         .                     . 
                          .                   .  
                           .                 .   
                            ..             ..    
                              ...       ...      
                                 .......         
```
Note that there is exactly one dot on each column.
* Each character in the input string will replace a dot in the shape above, from left to right.
* Spaces in the input have to be outputted like normal characters, in place of a dot.
* The starting character corresponds to the leftmost dot in the figure above.
* This is only one period, inputs can be longer than the number of dots above.
### Input
* Inputs are ASCII strings that contain only characters between ASCII decimal 32 (space) and ASCII decimal 126 (Tilde ~).
* Inputs will always be one line only (no linebreaks).
* Inputs can be taken via STDIN, function parameters, command line arguments, or anything similar.
### Output
* Output must be printed exactly like they are in the test cases given.
* Trailing spaces on lines are allowed as long as the length of the line with those trailing spaces does not exceed the length of the longest line (the one with the last character on it).
* No leading/trailing line allowed.
### Test cases
* Input: `.................................................`
Output:
```
         .......                                 
      ...       ...                              
    ..             ..                            
   .                 .                           
  .                   .                          
 .                     .                         
.                       .                       .
                         .                     . 
                          .                   .  
                           .                 .   
                            ..             ..    
                              ...       ...      
                                 .......         
```
* Input: `Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.`
Output:
```
         ng Puzz                                         ion and                                         siasts                                          stratio           
      mmi       les                                   est        an                                   thu       and                                   egi       n r        
    ra              &                               qu             sw                               en              c                                r             eq      
   g                                                                 e                                               o                             o                 u     
  o                   C                           a                   r                           e                   d                           n                   i    
 r                     o                                                                         l                     e                                               r   
P                       d                       s                       s                       z                                               ,                       e  
                         e                     i                         i                     z                         g                     e                         d 
                                                                          t                   u                           o                   e                           .
                           G                 e                             e                 p                             l                 r                             
                            ol             ng                                f             g                                fe              f                              
                              f S       cha                                   or        min                                   rs.       00%                                
                                 tack Ex                                         program                                          It's 1                                   
```
* Input: `Short text.`
Output:
```
         t.
      tex  
    t      
   r       
  o        
 h         
S          
```
* Input: `The quick brown fox jumps over the lazy dog`
Output:
```
          brown                            
      ick       fox                        
    qu              j                      
                     u                     
  e                   m                    
 h                     p                   
T                       s                  
                          o                
                           v               
                            er             
                               th       dog
                                 e lazy    
```
### Scoring
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest program or function in bytes wins.
  
[Answer]
## Python 2, 156 bytes
```
l=map(int,"654322111%08d1122345"%1);l+=[12-c for c in l]
def f(t):
 h=len(t);o=bytearray(' '*h+'\n')*13;i=0
 for c in t:o[i-~h*l[i%48]]=c;i+=1
 print o[:-1]
```
## Explanation
* The whole code simply makes a block of spaces (`o`) and replaces the right spaces with the letters of the input `t`.
* The variable `l` stores a list of offsets from the top. So that the `n`th character of `t` should be on line `l[n]`.
* The bytearray `o` serves as a mutable string, since strings are immutable in python.
* `-~h` is the same as `h+1` but saves space because I don't need parentheses.
[Answer]
# Pyth, 59 bytes (57 characters)
```
Xjb.sC.>V+R*12\ Xz\ C9*+-L12K+JsM._+6jC\཈2tP_JKlz]*dlzC9d
```
[Demonstration.](https://pyth.herokuapp.com/?code=Xjb.sC.%3EV%2BR*12%5C+Xz%5C+C9*%2B-L12K%2BJsM._%2B6jC%5C%E0%BD%882tP_JKlz%5D*dlzC9d&input=Short.+++++++++++++d&debug=0)
A binary lookup table is encoded inside `཈`, which has value 3912. This is converted to binary, giving `[1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0]`. This is treated as the differences between consecutive heights. By prepending a 6, forming all prefixes and mapping each to its sum, the first quarter of the wave is generated.
`sM._+6jC\཈2` evaluates to `[6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12]` as described above. Then, the code concatenates on the reverse of this string to form the first half of the wave, and then subtracts it from 12 to give the entire wave.
Then, we form lines of each input character followed by 12 spaces. This line is rotated to the right by the wave height parameter corresponding to that location, and then the lines are transposed and joined on newlines.
Then, we strip off leading and trailing blank lines. However, we can't strip off leading or trailing blank lines that have spaces from the input. This is implemented by replacing spaces in the input with tabs (`C9`), which can't be in the input, stripping blank lines, and turning the tabs back into spaces.
[Answer]
## Java, 219 209 199 bytes
```
void p(char[]s){int r=6,c;String t="";for(;r>-7;r--,t+='\n')for(c=0;c<s.length;c++)t+=(s(c%48)==r?s[c]:' ');System.out.println(t);}int s(int a){return a<4?a:a<6?4:a<9?5:a<15?6:a<24?s(24-a):-s(a-24);}
```
I'm still a newbie here, and hope that it is compliant to the rules to introduce a sub-function (when the bytes of this function are counted, of course). If not, I'll try to convert the `sin` function into some clever array lookup...
```
public class SinusText
{
    public static void main(String[] args)
    {
        SinusText s = new SinusText();
        s.p(".................................................".toCharArray());
        s.p("Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.".toCharArray());
        s.p("Short text.".toCharArray());
        s.p("The quick brown fox jumps over the lazy dog".toCharArray());
    }
    void p(char[]s){int r=6,c;String t="";for(;r>-7;r--,t+='\n')for(c=0;c<s.length;c++)t+=(s(c%48)==r?s[c]:' ');System.out.println(t);}int s(int a){return a<4?a:a<6?4:a<9?5:a<15?6:a<24?s(24-a):-s(a-24);}
}
```
[Answer]
# [Perl 5](https://www.perl.org/) + `-lF -Mbigint -M5.10.0`, 97 bytes
Coming back to this after a while it's nice to see how much my approach to this kind of thing has improved, -123 bytes!
```
eval's!.!(@l=654322111000000011122345=~/./g,map{12-$_}@l)[pos()%48]-$-?$":$F[pos]!ge;$-+=say;'x13
```
[Try it online!](https://tio.run/##K0gtyjH9/z@1LDFHvVhRT1HDIcfWzNTE2MjI0NDQAAKALCMjYxNT2zp9Pf10ndzEgmpDI12V@FqHHM3ogvxiDU1VE4tYXRVdexUlKxU3kFCsYnqqtYqutm1xYqW1eoWhMR2s@JdfUJKZn1f8X9ftv66vqZ6hgZ4BkJGUmZ6ZVwIA "Perl 5 – Try It Online")
## Explanation
Input is implicitly placed in `$_` (due to `-n`, and `-a`, being implicitly set by `-F` being set) and is split into chars in `@F`. Then the code in `'`s is `eval`ed 13 times. This code `s`ubstitues every char (`s!.!...!`) in the input (`s///` works on `$_` by default) with either the char at the current position from `@F` (`$F[pos]`) or a space (`$"`) depending on whether or not the current value of `$-` (which starts as `0`) is equal to the value in the in the list of values, modulo `48`. This list is constructed from the 24-digit integer (`654322111000000011122345`), which represents the first set of rows in which the char should be displayed for the waveform, which is split into digits (`=~/./g`) and the second part is created in the immediately following `map` which subtracts the values from `12`, resulting in a list of 48 values that indicate where chars should be displayed. `$-` is incremented using the return from `say` (which outputs the current value of `$_` with a trailing newline) which is `1`.
[Answer]
## JavaScript, ~~251~~ ~~243~~ ~~224~~ ~~220~~ 217
Really simple implementation: it uses a string of characters to represent the y-position of each character on the wave (offset by `a`, which is ASCII code 97). It then iterates through all possible rows; if the y-value of the current row is the same as the y-position on the wave, it writes a character from the string. There's also a cleanup at the end to remove the row if it turned out to be completely blank.
Note that the output will appear wonky in the `alert()` window if it's not using a monospaced font, you can change it to `console.log()` to verify the output is correct.
```
s=prompt(o=[])
for(y=i=0;y<13;++y){o[i]=""
for(x=0;x<s.length;++x)o[i]+=y=="gfedccbbbaaaaaaabbbccdefghijkklllmmmmmmmlllkkjih".charCodeAt(x%48)-97?s[x]:" "
if(o[i++].trim().length<1)o.splice(--i,1)}
alert(o.join("\n"))
```
EDIT1: `++` and `--` exist.
EDIT2: Blank line removal is now done in the same loop as the rest, saving 17 characters. Didn't need those brackets either, for an extra 2 characters.
EDIT3: No need to declare the waveform as a variable, saving 4 characters.
EDIT4: As pointed out by Dom Hastings in the comments, the byte count included the carriage return as well as the newline character, updated the byte counts for all revisions to exclude the carriage return.
EDIT5: Saved 3 bytes courtesy of Dom Hastings. I haven't implemented the `o.splice` fix as this fails to remove the blank lines (on my end, at least).
[Answer]
## Matlab, 133, 130 bytes
The one liner:
```
s=input('');y=ceil(5.6*sin(0:pi/24:pi-.1).^.9);l=[-y y]+7;n=numel(s);t=repmat(' ',13,n);for k=1:n;t(l(mod(k-1,48)+1),k)=s(k);end;t
```
And the expanded version:
```
function f(s)
    y=ceil(5.6*sin(0:pi/24:pi-.1).^.9);l=[-y y]+7;  %// calculate the line number for each column position
    n=numel(s);                                     %// number of character in input
    t=repmat(' ',13,n);                             %// Create a blank canvas of whitespace characters
    for k=1:n
        t(l(mod(k-1,48)+1),k)=s(k);                 %// place each input character where it should be
    end
    t                                               %// force the output display
```
---
The one liner takes input from the console (`stdin`) and is 130 bytes. The expanded version replace the console input by a function definition (+1 byte) but is much more comfortable to use for the test case in a loop:
---
**Description:** 
The line index of each character is calculated for a half period, then mirrored and concatenated to have a full period.  
We create a blank background of whitespace character (same length as the input string.
We place each character according to its position in the relevant line. If the input string is longer than one period, the `mod` (modulo) operator wraps that so we don't get out of bound when requesting the line number.
---
**Test case:** 
Save the function version under `textsine.m` in your path, then run: 
```
s = {'.................................................';...
    'Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It''s 100% free, no registration required.';...
    'Short text.';...
    'The quick brown fox jumps over the lazy dog'};
for txtcase=1:4
    textsine(s{txtcase,1})
end
```
will output:
```
t =
         .......                                 
      ...       ...                              
    ..             ..                            
   .                 .                           
  .                   .                          
 .                     .                         
.                       .                       .
                         .                     . 
                          .                   .  
                           .                 .   
                            ..             ..    
                              ...       ...      
                                 .......         
t =
         ng Puzz                                         ion and                                         siasts                                          stratio           
      mmi       les                                   est        an                                   thu       and                                   egi       n r        
    ra              &                               qu             sw                               en              c                                r             eq      
   g                                                                 e                                               o                             o                 u     
  o                   C                           a                   r                           e                   d                           n                   i    
 r                     o                                                                         l                     e                                               r   
P                       d                       s                       s                       z                                               ,                       e  
                         e                     i                         i                     z                         g                     e                         d 
                                                                          t                   u                           o                   e                           .
                           G                 e                             e                 p                             l                 r                             
                            ol             ng                                f             g                                fe              f                              
                              f S       cha                                   or        min                                   rs.       00%                                
                                 tack Ex                                         program                                          It's 1                                   
t =
         t.
      tex  
    t      
   r       
  o        
 h         
S          
t =
          brown                            
      ick       fox                        
    qu              j                      
                     u                     
  e                   m                    
 h                     p                   
T                       s                  
                          o                
                           v               
                            er             
                               th       dog
                                 e lazy    
```
---
if you want to test the one liner version with input from `stdin`, your input has to be entered as **one** single `string`, so you'd have to enclose your input between `'` characters.
Example:
```
'Short text.'   %//   valid input
Short text.     %// INVALID input
```
---
*Thanks `Luis Mendo` for shaving up 3 bytes ;-)*
[Answer]
# Scala 377 characters
first cut. probably can get a better formula to translate `x` to `y`
```
(s:String)⇒s.zipWithIndex.map(t⇒(t._1,t._2,t._2%48 match{
case i if i<5⇒6-i
case 5|19⇒2
case 6|7|8|16|17|18⇒1
case i if i<16⇒0
case i if i<29⇒i%20+2
case 29|43⇒10
case 30|31|32|40|41|42⇒11
case i if i<40⇒12
case i if i>43⇒10-i%44
})).groupBy(_._3).toSeq.map{case(y,xs)⇒(""→0/:xs.sortBy(_._2)){case((p,l),(c,x,_))⇒(p+" "*(x-l-1)+c)→x}._1→y}.sortBy(_._2).map(_._1).mkString("\n")
```
[Answer]
# Common Lisp, 205 bytes
```
(lambda(s &aux p v o)(dotimes(r 13)(setf o 0 p v v(round(*(/ 24 pi)(+(asin(-(/ r 6)1))pi))))(when p(map()(lambda(c)(princ(if(some(lambda(k)(<= p(mod k 48)(1- v)))`(,o,(- 23 o)))c" "))(incf o))s)(terpri))))
```
## Tests
See <http://pastebin.com/raw.php?i=zZ520FTU>
## Remarks
Print the output line by line, computing the indices in the strings that should be printed using the inverse sine function `asin`. The output do not match exactly the expected inputs in the question, but since OP acknowledges that the example outputs are not real sine, I guess this is ok. At least, there is always only one character written for each column.
[Answer]
# Python 2, 172 bytes
This isn't as good as [Alex L's answer](https://codegolf.stackexchange.com/a/53850/19349), but it's pretty close. Takes input from standard input and works best in a `.py` file.
```
l=map(int,bin(9960000)[2:]);l+=[-c for c in l];s=6;o=[];i=9
for c in raw_input():b=[' ']*13;b[s]=c;o+=[b];s+=l[i%48];i+=1
print''.join(sum(zip(*o+['\n'*13])[::-1],())[:-1])
```
I decided to build the output transposed (each column is a row) and then transpose the result, since in python the transpose of a matrix is `map(*m)`.
* `l`: The binary representation of `9960000` (after chopping off the `"0b"` from `bin`) is `100101111111101001000000`. This is the "step" of the sine wave each column, starting at the very last character of the very lowest point. I copy this list, negate each number, and tack it onto the end of itself to form what is effectively a derivative of the function.
* `s`: This is the variable that keeps track of which row (column in the transpose) the next character gets inserted into.
* `o`: End output, transposed
* `i`: Keeps track of sine wave period. Starts at 9 since `l` is shifted slightly.
In the `for` loop, I create a list of 13 spaces (I was using bytearrays but lists of characters turn out to have a shorter print statement), then replace the `s`th character with the input character. Append `b` to the end of `o`, add the appropriate step to `s`, and increment `i`.
I had hoped the `print` statement would be as simple as `\n'.join(*zip(o))`, but no such luck. `zip(*o+['\n'*13])[::-1]` appends a column of newlines and then reverses and transposes the whole thing (without the reversing, the sine wave is upside down), `sum(...,())` concatenates the tuples together into one tuple of characters, and then `''.join(...)` concatenates the characters and prints it.
Other things I tried were making a 12-character array of spaces and inserting the new character into the appropriate place, and replacing `l+=[-c for c in l];` with some sort of math with some sort of multiplication of `1` and `-1` with the result of indexing into `l`, but nothing I could come up with ended up being shorter.
[Answer]
# Mathematica, 131 bytes
```
i=[input string];c=Characters@i;l=Length@c;StringJoin@Riffle[StringJoin@@@SparseArray[Table[{7-Round[6 Sin[.13(x-1)]],x},{x,l}]->c,{13,l}," "],"\n"]
```
That's 131 characters, including the three for `i=foo;`. That seemed a reasonable way to take the input; I could have put it straight into the definition of `c` and saved a few strokes, but that feels unfair.
It's pretty straightforward -- almost even readable. It splits the string into a list of characters, and then puts those characters into a sparse array at the positions determined from the `Table` (any spot in the array not given a character defaults to a space). The lines are assembled separately, then newlines sprinkled between them. The final StringJoin stitches it all up.
**NB:** Like some other solutions, this may not actually be valid because it produces a real sinusoid rather than the (beautiful) handcrafted example.
## Tests:
```
(*i=Programming Puzzles...*)
         ng Puzz                                          on and                                          iasts                                           tration          
       mi       le                                     sti       a                                      us      and                                     is        r        
     am           s                                   e           ns                                  th            c                                 eg           eq      
    r               &                               qu              we                              en               o                               r               u     
  og                  C                                               r                                               d                            o                  ir   
 r                     o                          a                                               e                    e                          n                     e  
P                       d                       s                       si                       l                       g                                               d 
                         e                     i                          t                    zz                         o                     ,                         .
                           G                                               e                  u                            lf                 ee                           
                            o               ge                               f               p                               e               r                             
                             lf           an                                  or           g                                  rs            f                              
                                St      ch                                       p      min                                     .        0%                                
                                  ack Ex                                          rogram                                          It's 10                                  
(*i=.... ...*)
         .......                                 
       ..       ..                               
     ..           ..                             
    .               .                            
  ..                 ..                          
 .                     .                         
.                       .                       .
                         ..                    . 
                           .                  .  
                            .               ..   
                             ..           ..     
                               ...      ..       
                                  ......         
(*i= Short text.*)
         t.
       ex  
      t    
    t      
  or       
 h         
S          
           
           
           
           
           
(*i=The quick...*)              
          brown                            
       ck       fo                         
     ui           x                        
    q               j                      
  e                  um                    
 h                     p                   
T                       s                  
                          o                
                           v               
                            e              
                             r            g
                               the      do 
                                   lazy    
```
]