Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zipped String from 2 (or more) Strings - "AB" + "YZ" = "AYBZ"

So I am trying to return another String from 2 input sentences zipped together. If the 2 sentences are identical in length it will produce an actual output. If the two input sentences are not identical in length then it will just return an empty string. Here is my code so far but I can't figure out how to zip the words correctly could someone help me. BTW it would be nice if you could help me by doing this recursively because I'm trying to practice that.

Ex:

Zippppp("ABC", "123") will return "A1B2C3"
Zippppp("AD", "CCC") will return “”
public class Zippppp
{
    public Zippppp(String a, String s)
    {
       int l1 = a.length();
       int l2 = s.length();
       if(l1 == l2)
          for(int i = 0; i > l1; i++)          
             System.out.print( a.substring(0, 1) + s.substring(0, 1));
     }
      
     public static void main(String args[ ])
     {
        Zippppp sv = new Zippppp("ABC", "123");
        System.out.print(sv);
     }
}
like image 888
ozmrur Avatar asked Dec 06 '22 08:12

ozmrur


1 Answers

I love your class name. Sincerely

In order to really "return" it, you could implement something similar to the examples below.

Update/Edit: The original answer is below, as the three new approaches (which don't care about the number of strings to zip) are on top.


[MultiThreaded]

The ultimate ZIPPER

Each of the words to zip is handled by a thread. Why? Ask yourself: WHY NOT???

Boredom makes this things happen.

Each word will be lovely processed by its own thread. Threads organize themselves in order not to process the same word and set the same positions thanks to the AtomicInteger.

String[] mix =new String[]{"AAAZZZ","100001","BBBWWW","200002","CCCYYY","300003",
                           "DDDXXX", "400004","EEEWWW","5000005","FFFVVV","600006"};

int strl = mix[0].length();        //entry's length
int nwords = mix.length;           //number of strings
char[] zip=new char[strl*nwords];  //the result

AtomicInteger myWord = new AtomicInteger(0);
//returning boolean if want to check some future failed(not here lol)
List<Callable<Boolean>> callables = new ArrayList<>(nwords);  
Callable<Boolean> zipYours =
    new Callable<Boolean>() 
    {  
        public Boolean call() 
        {  
           try
           {
              int mine = myWord.getAndIncrement();
              for (int x=0; x < strl; x++)
                  zip[mine+(nwords*x)]=mix[mine].charAt(x);

            }catch(Exception e) {
               return false;
            }               
           
            return true;
         }  
     };
         
 for (int i=0;i<nwords;i++)
      callables.add(zipYours);
     
 //one thread - one word - true loef
 ExecutorService executor = Executors.newFixedThreadPool(nwords);
 executor.invokeAll(callables);  
 executor.shutdown();  

 System.out.println(new String(zip));
 /*A1B2C3D4E5F6A0B0C0D0E0F0A0B0C0D0E0F0Z0W0Y0X0W0V0Z0W0Y0X0W0V0Z1W2Y3X4W0V6*/

Was this required by any means? OF COURSE NOT. But it was fun, and my girlfriend told me to do it.

Lie, I don't have a girlfriend. Do you really think I'd be doing this if I had one??


[Zip'em all]

Two different approaches:

1. Direct move

Works regardless of the number of strings to zip, from 2 to n.* This means these approaches are also the replacement of the old methods, as you can either call getStringsZippedDirectMove("ABC,"123") or getStringsZippedDirectMove(yourArray).

In this approach, each string is completely allocated at a time, so each element in the list is only accessed/processed once. The main loop iterates based on the number of elements in the array:

public static String getStringsZippedDirectMove(String... mix) 
{    
   if (!goodMix(mix))
       return "woloolooO";                //you are a blue monk now
   
   int cn = mix[0].length(), n = mix.length;   //cn = 3 | n = 6 
   char[] zip=new char[cn*n];
  
   for (int i=0; i<n; i++) 
       for (int x=0; x<cn; x++)
           zip[i+(n*x)] = mix[i].charAt(x);
      
   return  new String(zip);  
}

boolean goodMix(String ... mix)
{
   if (mix.length<2) 
      return false;              
   for (int i=1; i<mix.length; i++)
      if (mix[i].length()!=mix[0].length())
         return false;        
   return true;
}

For example, for the first String: "AAA":

zip[i+(n*x)]=mix[i].charAt(x); // zip[0 + (6*0)]=mix[0].charAt(0); 
zip[i+(n*x)]=mix[i].charAt(x); // zip[0 + (6*1)]=mix[0].charAt(1);
zip[i+(n*x)]=mix[i].charAt(x); // zip[0 + (6*2)]=mix[0].charAt(2); 
          
            zip[0]=A      zip[6]=A     zip[12]=A  

For the last String: "789":

zip[i+(n*x)]=mix[i].charAt(x); // zip[5 + (6*0)]=mix[5].charAt(0); 
zip[i+(n*x)]=mix[i].charAt(x); // zip[5 + (6*1)]=mix[5].charAt(1);
zip[i+(n*x)]=mix[i].charAt(x); // zip[5 + (6*2)]=mix[5].charAt(2); 
          
            zip[5]=7      zip[11]=8     zip[17]=9  

enter image description here

Same output:

 String[] mix =new String[] { "AAA","123","BBB","456","CCC","789"};
 System.out.println(getStringsZippedDirectMove(mix));   //"A1B4C7A2B5C8A3B6C9"

Each iteration leads to the complete relocation of the String element's chars.

2. Multi move from index - Holger style

Motivated by Holger's comments

This also will work regardless of the number of strings to zip, from 2 to n.*

public String getStringsZippedHolger(String ... mix) 
{    
   if (!goodMix(mix))
      return "woloolooO";           //you are a red monk now

   char[] zip = new char[mix[0].length()*mix.length];    
   for (int i=0, j=0; i<mix[0].length(); i++) 
      for (String s : mix)
          zip[j++] = s.charAt(i);

   return new String(zip);  
}

The main loop iterates three times, as it's based on each text's length (3). At each iteration, it will append the char at position i from each of the Strings in the array in the index marked by j. This last counter increments at each assignation.

enter image description here

 String[] mix =new String[] { "AAA","123","BBB","456","CCC","789"};
 System.out.println(getStringsZippedHolger(mix));         // "A1B4C7A2B5C8A3B6C9"

 System.out.println(getStringsZippedHolger("HLE","OGR"));
 System.out.println(getStringsZippedHolger("IT S","SHBS"," EO "));


Original answer block (2 strings)

Arrays

Double assignation at each iteration

public String getZippppppppppppppppppppppppp(String a, String s)  //a -"ABC" s -"123"
{    
   if (s.length()!=a.length())
      return "";
   char[] zip=new char[s.length()*2];      
   for (int i=0; i<s.length(); i++) 
   {
      zip[i*2] = a.charAt(i);   
      zip[(i*2)+1] = s.charAt(i);  
   }  
   return new String(zip);  /* "A1B2C3" */
}

Loop over the length of any of the Strings and insert each element in order. During the iterations, this are the assigned values:

             i = 0              i = 1             i = 2
      --------------------------------------------------------
            zip[0] = A        zip[2] = B         zip[4] = C
            zip[1] = 1        zip[3] = 2         zip[5] = 3
  

Horrendous paint:

enter image description here

As a result, we got:

zip = ['A','1','B','2','C','3'] ||| new String(zip) = "A1B2C3"

Note: If you don't love arrays, you have no hearth.

Single assignation at each iteration

This uses another approach for the iteration logic, which seems totally useless when you can do what the previous example does. but just for fun.

static String getZipppppppppppppppppppppUsingCharAtThanksElliot(String a, String s)  
{                                                                 //a -"ABC" s -"123"
  if (a.length()!=s.length()) 
      return "";
  char[] zip = new char[s.length()*2];
  int c=0;
  boolean even = false;
  for(int i =0; i < (s.length()*2); i++) 
  {
     even =!even;
     if (even) 
        zip[i] = a.charAt(c); 
     else 
     {      
        zip[i] = s.charAt(c);
        c++; 
     }   
   }
   
   return new String(zip);  //--> "A1B2C3"
}

String#subString:

public String getZippppppppppppppppppppppppp(String a, String s)  //a -"ABC" s -"123"
{
    if (a.length()!=s.length()) 
        return "";
    String line="";
    for(int i = 0; i < s.length(); i++)
        line += ( a.substring(i*1, (i*1)+1) + s.substring(i*1, (i*1)+1) );

    return line;  //--> "A1B2C3"
}

Probably the worst performant approach.


String#charAt

Note that charAt(), correctly pointed out on Elliot's answer, will not work with this logic; it will give you a numeric text, as result of adding their respective unicode values. It won't append the characters.

Alternatives to work with charAt() would be using the empty string workaround, or creating a char[] as in the second boring example.

public String getZipppppppppppppppppppppUsingCharAtThanksElliot(String a, String s)  
{                                                                 //a -"ABC" s -"123"
    if (a.length()!=s.length()) 
        return "";
    String line="";
    for(int i = 0; i < s.length(); i++)
        line +=  a.charAt(i) + "" + s.charAt(i) ; //note the empty string

    return line;  //--> "A1B2C3"
}
like image 158
aran Avatar answered Dec 18 '22 02:12

aran