Advertisement
Marrin

Panorama

Mar 12th, 2016
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.95 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. static const char *SLOPES = "\\_/";
  6. static char *error_message = NULL;
  7.  
  8. typedef struct
  9. {
  10.     int width, height;
  11.     char data[];
  12. } Panorama;
  13.  
  14.  
  15. int check_source(char *source)
  16. {
  17.     ssize_t total_length, slope_length;
  18.  
  19.     total_length = strlen(source);
  20.     slope_length = strspn(source, SLOPES);
  21.     return (total_length == slope_length) ? total_length : -1;
  22. }
  23.  
  24.  
  25. int slope_to_delta(char slope)
  26. {
  27.     return strchr(SLOPES, slope) - SLOPES - 1;
  28. }
  29.  
  30.  
  31. uint* calculate_heights(uint width, char *source, int *max_height)
  32. {
  33.     uint i;
  34.     int current_height, delta;
  35.     uint *heights;
  36.  
  37.     heights = malloc(width * sizeof(heights));
  38.     *max_height = 0;
  39.     for (current_height = i = 0; i < width; ++i) {
  40.         heights[i] = current_height;
  41.         delta = slope_to_delta(source[i]);
  42.         current_height += delta;
  43.         if (current_height < 0) {
  44.             free(heights);
  45.             error_message = "panorama drops below baseline";
  46.             return NULL;
  47.         }
  48.         if (delta == -1) heights[i] = current_height;
  49.         if (current_height > *max_height) *max_height = current_height;
  50.     }
  51.     ++*max_height;
  52.     return heights;
  53. }
  54.  
  55.  
  56. Panorama* Panorama_new(int width, int height, char *source, uint *heights)
  57. {
  58.     Panorama *result;
  59.     int data_size;
  60.     int i;
  61.  
  62.     data_size = width * height;
  63.     result = malloc(sizeof(*result) + data_size);
  64.     result->width = width;
  65.     result->height = height;
  66.     memset(result->data, ' ', data_size);
  67.     for (i = 0; i < width; ++i) {
  68.         result->data[width * (height - heights[i] - 1) + i] = source[i];
  69.     }
  70.  
  71.     return result;
  72. }
  73.  
  74.  
  75. Panorama* Panorama_from_string(char *source)
  76. {
  77.     int width, height;
  78.     uint *heights;
  79.     Panorama *result = NULL;
  80.  
  81.     width = check_source(source);
  82.     if (width == -1) {
  83.         error_message = "illegal characters in argument";
  84.         return NULL;
  85.     }
  86.     heights = calculate_heights(width, source, &height);
  87.     if (heights) {
  88.         result = Panorama_new(width, height, source, heights);
  89.         free(heights);
  90.     }
  91.     return result;
  92. }
  93.  
  94.  
  95. void Panorama_print(Panorama *panorama)
  96. {
  97.     int i, j;
  98.     char *ptr;
  99.  
  100.     ptr = panorama->data;
  101.     for (i = 0; i < panorama->height; ++i) {
  102.         for (j = 0; j < panorama->width; ++j) {
  103.             putchar(*ptr++);
  104.         }
  105.         putchar('\n');
  106.     }
  107. }
  108.  
  109.  
  110. void Panorama_free(Panorama *panorama)
  111. {
  112.     if (panorama) {
  113.         panorama->width = panorama->height = 0;
  114.         free(panorama);
  115.     }
  116. }
  117.  
  118.  
  119. int main(int argc, char **argv)
  120. {
  121.     Panorama *panorama;
  122.  
  123.     if (argc < 2) {
  124.         printf("usage: %s panoramastring\n", argv[0]);
  125.         return 1;
  126.     }
  127.  
  128.     panorama = Panorama_from_string(argv[1]);
  129.     if (panorama) {
  130.         Panorama_print(panorama);
  131.         Panorama_free(panorama);
  132.     } else {
  133.         puts(error_message);
  134.         return 2;
  135.     }
  136.  
  137.     return 0;
  138. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement