Determine if a character string is   squeezable.

And if so,   squeeze the string   (by removing any number of
a   specified   immediately repeated   character).



This task is very similar to the task     Determine if a character string is collapsible     except
that only a specified character is   squeezed   instead of any character that is immediately repeated.



If a character string has a specified   immediately repeated   character(s),   the repeated characters are to be
deleted (removed),   but not the primary (1st) character(s).



A specified   immediately repeated   character is any specified character that is   immediately  
followed by an identical character (or characters).   Another word choice could've been   duplicated
character,   but that might have ruled out   (to some readers)   triplicated characters   ···   or more.



{This Rosetta Code task was inspired by a newly introduced   (as of around
November 2019)   PL/I   BIF:   squeeze.}



Examples

In the following character string with a specified   immediately repeated   character of   e:



 The better the 4-wheel drive, the further you'll be from help when ya get stuck! 



Only the 2nd   e   is an specified repeated character,   indicated by an underscore
(above),   even though they (the characters) appear elsewhere in the character string.



So, after squeezing the string, the result would be:

 The better the 4-whel drive, the further you'll be from help when ya get stuck! 





Another example:
In the following character string,   using a specified immediately repeated character   s:

 headmistressship 



The "squeezed" string would be:

 headmistreship 



Task

Write a subroutine/function/procedure/routine···   to locate a   specified immediately repeated   character
and   squeeze   (delete)   them from the character string.   The
character string can be processed from either direction.



Show all output here, on this page:

   the   specified repeated character   (to be searched for and possibly squeezed):
   the   original string and its length
   the resultant string and its length
   the above strings should be "bracketed" with   <<<   and   >>>   (to delineate blanks)
   «««Guillemets may be used instead for "bracketing" for the more artistic programmers,   shown used here»»»


Use (at least) the following five strings,   all strings are length seventy-two (characters, including blanks),   except
the 1st string:

                                                                                  immediately
 string                                                                            repeated
 number                                                                            character
                                                                                     ( ↓   a blank,  a minus,  a seven,  a period)
        ╔╗
   1    ║╚═══════════════════════════════════════════════════════════════════════╗    ' '    ◄■■■■■■  a null string  (length zero)
   2    ║"If I were two-faced, would I be wearing this one?" --- Abraham Lincoln ║    '-'
   3    ║..1111111111111111111111111111111111111111111111111111111111111117777888║    '7'
   4    ║I never give 'em hell, I just tell the truth, and they think it's hell. ║    '.'
   5    ║                                                    --- Harry S Truman  ║  (below)  ◄■■■■■■  has many repeated blanks
        ╚════════════════════════════════════════════════════════════════════════╝     ↑
                                                                                       │
                                                                                       │
        For the 5th string  (Truman's signature line),  use each of these  specified immediately  repeated characters:
                                  •  a blank
                                  •  a minus
                                  •  a lowercase  r



Note:   there should be seven results shown,   one each for the 1st four strings,   and three results for
the 5th string.


Other tasks related to string operations:

Metrics
 Array length
 String length
 Copy a string
 Empty string  (assignment)
Counting
 Word frequency
 Letter frequency
 Jewels and stones
 I before E except after C
 Bioinformatics/base count
 Count occurrences of a substring
 Count how many vowels and consonants occur in a string
Remove/replace
 XXXX redacted
 Conjugate a Latin verb
 Remove vowels from a string
 String interpolation (included)
 Strip block comments
 Strip comments from a string
 Strip a set of characters from a string
 Strip whitespace from a string -- top and tail
 Strip control codes and extended characters from a string
Anagrams/Derangements/shuffling
 Word wheel
 ABC problem
 Sattolo cycle
 Knuth shuffle
 Ordered words
 Superpermutation minimisation
 Textonyms (using a phone text pad)
 Anagrams
 Anagrams/Deranged anagrams
 Permutations/Derangements
Find/Search/Determine
 ABC words
 Odd words
 Word ladder
 Semordnilap
 Word search
 Wordiff  (game)
 String matching
 Tea cup rim text
 Alternade words
 Changeable words
 State name puzzle
 String comparison
 Unique characters
 Unique characters in each string
 Extract file extension
 Levenshtein distance
 Palindrome detection
 Common list elements
 Longest common suffix
 Longest common prefix
 Compare a list of strings 
 Longest common substring
 Find common directory path
 Words from neighbour ones
 Change e letters to i in words
 Non-continuous subsequences
 Longest common subsequence
 Longest palindromic substrings
 Longest increasing subsequence
 Words containing "the" substring
 Sum of the digits of n is substring of n
 Determine if a string is numeric
 Determine if a string is collapsible
 Determine if a string is squeezable
 Determine if a string has all unique characters
 Determine if a string has all the same characters
 Longest substrings without repeating characters
 Find words which contains all the vowels
 Find words which contains most consonants
 Find words which contains more than 3 vowels
 Find words which first and last three letters are equals
 Find words which odd letters are consonants and even letters are vowels or vice_versa
Formatting
 Substring
 Rep-string
 Word wrap
 String case
 Align columns
 Literals/String
 Repeat a string
 Brace expansion
 Brace expansion using ranges
 Reverse a string
 Phrase reversals
 Comma quibbling
 Special characters
 String concatenation
 Substring/Top and tail
 Commatizing numbers
 Reverse words in a string
 Suffixation of decimal numbers
 Long literals, with continuations 
 Numerical and alphabetical suffixes
 Abbreviations, easy
 Abbreviations, simple
 Abbreviations, automatic
Song lyrics/poems/Mad Libs/phrases
 Mad Libs
 Magic 8-ball
 99 Bottles of Beer
 The Name Game (a song)
 The Old lady swallowed a fly
 The Twelve Days of Christmas
Tokenize
 Text between
 Tokenize a string
 Word break problem
 Tokenize a string with escaping
 Split a character string based on change of character
Sequences
 Show ASCII table
 De Bruijn sequences
 Self-referential sequences
 Generate lower case ASCII alphabet




 
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
 
#define COLLAPSE 0
#define SQUEEZE 1
 
typedef struct charList{
    char c;
    struct charList *next;
} charList;
 
/*
Implementing strcmpi, the case insensitive string comparator, as it is not part of the C Standard Library.
 
Comment this out if testing on a compiler where it is already defined.
*/
 
int strcmpi(char str1[100],char str2[100]){
    int len1 = strlen(str1), len2 = strlen(str2), i;
 
    if(len1!=len2){
        return 1;
    }
 
    else{
        for(i=0;i<len1;i++){
            if((str1[i]>='A'&&str1[i]<='Z')&&(str2[i]>='a'&&str2[i]<='z')&&(str2[i]-65!=str1[i]))
                return 1;
            else if((str2[i]>='A'&&str2[i]<='Z')&&(str1[i]>='a'&&str1[i]<='z')&&(str1[i]-65!=str2[i]))
                return 1;
            else if(str1[i]!=str2[i])
                return 1;
        }
    }
 
    return 0;
}
 
charList *strToCharList(char* str){
    int len = strlen(str),i;
 
    charList *list, *iterator, *nextChar;
 
    list = (charList*)malloc(sizeof(charList));
    list->c = str[0];
    list->next = NULL;
 
    iterator = list;
 
    for(i=1;i<len;i++){
        nextChar = (charList*)malloc(sizeof(charList));
        nextChar->c = str[i];
        nextChar->next = NULL;
 
        iterator->next = nextChar;
        iterator = nextChar;
    }
 
    return list;
}
 
char* charListToString(charList* list){
    charList* iterator = list;
    int count = 0,i;
    char* str;
 
    while(iterator!=NULL){
        count++;
        iterator = iterator->next;
    }
 
    str = (char*)malloc((count+1)*sizeof(char));
    iterator = list;
 
    for(i=0;i<count;i++){
        str[i] = iterator->c;
        iterator = iterator->next;
    }
 
    free(list);
    str[i] = '\0';
 
    return str;
}
 
char* processString(char str[100],int operation, char squeezeChar){
    charList *strList = strToCharList(str),*iterator = strList, *scout;
 
    if(operation==SQUEEZE){
        while(iterator!=NULL){
            if(iterator->c==squeezeChar){
                scout = iterator->next;
 
                while(scout!=NULL && scout->c==squeezeChar){
                        iterator->next = scout->next;
                        scout->next = NULL;
                        free(scout);
                        scout = iterator->next;
                }
            }
            iterator = iterator->next;
        }
    }
 
    else{
        while(iterator!=NULL && iterator->next!=NULL){
            if(iterator->c == (iterator->next)->c){
                scout = iterator->next;
                squeezeChar = iterator->c;
 
                while(scout!=NULL && scout->c==squeezeChar){
                        iterator->next = scout->next;
                        scout->next = NULL;
                        free(scout);
                        scout = iterator->next;
                }
            }
            iterator = iterator->next;
        }
    }
 
    return charListToString(strList);
}
 
void printResults(char originalString[100], char finalString[100], int operation, char squeezeChar){
    if(operation==SQUEEZE){
        printf("Specified Operation : SQUEEZE\nTarget Character : %c",squeezeChar);
    }
 
    else
        printf("Specified Operation : COLLAPSE");
 
    printf("\nOriginal %c%c%c%s%c%c%c\nLength : %d",174,174,174,originalString,175,175,175,(int)strlen(originalString));
    printf("\nFinal    %c%c%c%s%c%c%c\nLength : %d\n",174,174,174,finalString,175,175,175,(int)strlen(finalString));
}
 
int main(int argc, char** argv){
    int operation;
    char squeezeChar;
 
    if(argc<3||argc>4){
        printf("Usage : %s <SQUEEZE|COLLAPSE> <String to be processed> <Character to be squeezed, if operation is SQUEEZE>\n",argv[0]);
        return 0;
    }
 
    if(strcmpi(argv[1],"SQUEEZE")==0 && argc!=4){
        scanf("Please enter characted to be squeezed : %c",&squeezeChar);
        operation = SQUEEZE;
    }
 
    else if(argc==4){
        operation = SQUEEZE;
        squeezeChar = argv[3][0];
    }
 
    else if(strcmpi(argv[1],"COLLAPSE")==0){
        operation = COLLAPSE;
    }
 
    if(strlen(argv[2])<2){
        printResults(argv[2],argv[2],operation,squeezeChar);
    }
 
    else{
        printResults(argv[2],processString(argv[2],operation,squeezeChar),operation,squeezeChar);
    }
 
    return 0;
}
 