জাভা 8 লাম্বদা, 1506 1002 972 942 টি অক্ষর
আমি এই চ্যালেঞ্জটি পরাজিত করতে চেয়েছিলাম, কারণ এটি অত্যন্ত আকর্ষণীয়। ফলাফল (খুব গল্ফ নয়) এখানে দেখা যায়:
import java.util.*;f->{Set<double[]>B=new HashSet(),r,n;double a,M,m,P=Math.PI*2,z=.5;int x=0,y,v=0,i,j,c[],p,q,l=g.length;for(;x<l;x++)for(y=0;y<g[x].length;y++)if(g[x][y]>63)for(;;){c=new int[]{-1};M=2e31-1;for(i=0;i<l;i++)for(j=0;j<g[i].length;j++)if(g[i][j]==42)if((m=(p=x-i)*p+(q=y-j)*q)<M){M=m;c=new int[]{i,j};}if(c[0]<0)break;g[c[0]][c[1]]=0;double[]A={(a=Math.atan2((c[1]-=y)-z,(c[0]-=x)-z))<0?a+P:a,(a=Math.atan2(c[1]+z,c[0]-z))<0?a+P:a,(a=Math.atan2(c[1]+z,c[0]+z))<0?a+P:a,(a=Math.atan2(c[1]-z,c[0]+z))<0?a+P:a};r=new HashSet();M=-P;m=P;for(double d:A){M=d>M?d:M;m=d<m?d:m;}r.add(new double[]{m,M});for(double[]t:B){n=new HashSet();for(double[]h:r)for(double[]u:t[0]<h[0]?t[1]<h[0]?new double[][]{h}:t[1]<h[1]?new double[][]{{t[1],h[1]}}:new double[0][]:t[0]>h[1]?new double[][]{h}:t[1]>h[1]?new double[][]{{h[0],t[0]}}:new double[][]{{h[0],t[0]},{t[1],h[1]}})if(u[0]<u[1])n.add(u);r=n;}B.addAll(r);if(!r.isEmpty())v++;}return v;}
অবশ্যই এটি অসম্পূর্ণ সংস্করণেও বিদ্যমান:
import java.util.*;
public class AngleCheck {
static int getViewableBuildingsC(char[][] grid) {
Set<double[]> blocked = new HashSet(), ranges, newRanges;
double angle, max, min, PI2 = Math.PI * 2, half = 0.5;
int x = 0, y, viewable = 0, i, j, building[], dX, dY, length = grid.length;
for (; x < length; x++) {
for (y = 0; y < grid[x].length; y++) {
if (grid[x][y] > 63) {
for (;;) {
building = new int[]{-1};
max = 2e31-1;
for (i = 0; i < length; i++) {
for (j = 0; j < grid[i].length; j++) {
if (grid[i][j] == 42) {
if ((min = (dX = x - i) * dX + (dY = y - j) * dY) < max) {
max = min;
building = new int[]{i, j};
}
}
}
}
if (building[0] < 0)
break;
grid[building[0]][building[1]] = 0;
double[] angles = {
(angle = Math.atan2((building[1] -= y) - half, (building[0] -= x) - half)) < 0 ? angle + PI2 : angle,
(angle = Math.atan2(building[1] + half, building[0] - half)) < 0 ? angle + PI2 : angle,
(angle = Math.atan2(building[1] + half, building[0] + half)) < 0 ? angle + PI2 : angle,
(angle = Math.atan2(building[1] - half, building[0] + half)) < 0 ? angle + PI2 : angle};
ranges = new HashSet();
max = -PI2;
min = PI2;
for (double d : angles) {
max = d > max ? d : max;
min = d < min ? d : min;
}
ranges.add(new double[]{min, max});
for (double[] reference : blocked) {
newRanges = new HashSet();
for (double[] currentRange : ranges) {
for (double[] subRange : reference[0] < currentRange[0] ?
reference[1] < currentRange[0] ?
// whole range after referencerange
new double[][]{currentRange}
:
reference[1] < currentRange[1] ?
// lower bound inside referencerange, but upper bound outside
new double[][]{{reference[1], currentRange[1]}}
:
// whole range inside referencerange -> nothing free
new double[0][]
:
// greater or equal lower bound
reference[0] > currentRange[1] ?
// whole range before referencerange
new double[][]{currentRange}
:
// ranges overlap
reference[1] > currentRange[1] ?
// range starts before and ends in reference range
new double[][]{{currentRange[0], reference[0]}}
:
// referencerange is in the range -> two free parts, one before, one after this
new double[][]{{currentRange[0], reference[0]}, {reference[1], currentRange[1]}}) {
if (subRange[0] < subRange[1])
newRanges.add(subRange);
}
}
ranges = newRanges;
}
blocked.addAll(ranges);
if (!ranges.isEmpty()) {
viewable++;
}
}
}
}
}
return viewable;
}
}
সুতরাং এটি দেখতে খুব কঠিন দেখাচ্ছে তবে এটি মনে করার চেয়ে সহজ উপায়। আমার প্রথম ধারণাটি ছিল আমার পজিশন থেকে বিল্ডিংয়ের কোনও লাইন কোনও ছেদ ছাড়াই তৈরি করা যায় কিনা তা পরীক্ষা করার জন্য কিছু ছেদটি অ্যালগরিদম ব্যবহার করা to এটি করার জন্য আমি কোহেন-সুদারল্যান্ড অ্যালগরিদম ব্যবহার এবং বিল্ডিংয়ের চারটি কোণে লাইন আঁকানোর সিদ্ধান্ত নিয়েছি। এটি প্রথম পরীক্ষাগুলির জন্য বেশ ভাল কাজ করেছে, তবে শেষটি ব্যর্থ হয়েছিল। আমি শীঘ্রই খুঁজে পেয়েছি, এটি এমন একটি ঘটনা যেখানে আপনি কোণগুলি দেখতে পাচ্ছেন না তবে একটি প্রান্তের একটি অংশ। তাই আমি ভেবেছিলাম এমন কিছু ধরণের রে কাস্টিংয়ের কথা যেমন @ ব্লু এটি করেছে। আমি কিছুটা অগ্রগতি না পাওয়ায় আমি সেই চ্যালেঞ্জটিকে সরিয়ে দিয়েছি। তারপরে আমি নীলির উত্তর দেখেছি এবং নিম্নলিখিত সাধারণ ধারণাটি আমার মনে এসেছিল: প্রতিটি বিল্ডিং এমন একটি কোণকে বাধা দেয় যেখানে অন্য কোনও কিছুই দেখা যায় না। আমাকে কেবল কী দেখা যায় এবং অন্যান্য ইমারতগুলির দ্বারা ইতিমধ্যে কী লুকানো আছে তার খোঁজ রাখা দরকার। এটাই!
অ্যালগরিদম নিম্নলিখিত হিসাবে কাজ করে: এটি ব্যক্তির সবচেয়ে ছোট দূরত্ব সহ বিল্ডিংটি নির্ধারণ করে। তারপরে আমরা ব্যক্তি থেকে বিল্ডিংয়ের কোণে টানা চারটি লাইন কল্পনা করি। এর মধ্যে দুটির একটি চূড়ান্ত মান রয়েছে: সর্বনিম্ন এবং সর্বোচ্চ কোণ যাতে বিল্ডিংটি দেখা যায়। আমরা এগুলিকে একটি ব্যাপ্তি হিসাবে গ্রহণ করি এবং তাদের সাথে অন্যান্য বিল্ডিংয়ের সাথে তুলনা করি যা আমরা জানি যে তারা দেখা যায় (শুরুতে কিছুই নেই)। ব্যাপ্তিগুলি একে অপরকে ওভারল্যাপ করতে পারে, একে অপরকে অন্তর্ভুক্ত করতে পারে বা একেবারে স্পর্শ করে না। আমি রেঞ্জগুলি তুলনা করি এবং বিল্ডিংয়ের কয়েকটি নতুন রেঞ্জ পাই যা দেখতে পাওয়া যায় না এমন দালানগুলির দ্বারা গোপন নয়। দর্শনীয় স্থানগুলির সাথে এটির তুলনা করার পরে যদি কিছু অবশিষ্ট থাকে তবে বিল্ডিংটিও দৃশ্যমান। আমরা পরের দীর্ঘ দূরত্বের সাথে পরবর্তী বিল্ডিংয়ের সাথে তুলনা করতে এবং শুরু করার জন্য রেঞ্জগুলির তালিকায় অবশিষ্ট কোণ রেঞ্জ যুক্ত করি।
কখনও কখনও সীমাগুলি এমনভাবে ওভারল্যাপ হতে পারে যে আমি 0 ডিগ্রি ব্যাপ্তির সাথে শেষ করি। এই রেঞ্জগুলি ভুলভাবে এমন একটি বিল্ডিংয়ের জন্য ফিল্টার করা হবে যা এমনকি দেখা যায় না।
আমি আশা করি কেউ এই ব্যাখ্যাটি বুঝতে পেরেছে :)
আমি জানি এই কোডটি খুব বেশি গল্ফ হয় না, আমি এটিকে তাত্ক্ষণিকভাবে করব।
এটি ছিল সত্যিই চ্যালেঞ্জিং কাজ। আপনি ভেবেছিলেন যে এমন একটি সমাধান খুঁজে পেয়েছে যা কাজ করে তবে পরিবর্তে আপনি এখনও অনেক দূরে। আমি মনে করি এই সমাধানটি বেশ ভাল কাজ করে। এটি খুব দ্রুত নয় তবে অন্তত এটি কাজ করে;) সেই ধাঁধার জন্য ধন্যবাদ!
হালনাগাদ
আমি পুরো জিনিসটি একটি একক কার্যক্রমে ডুবিয়ে দেওয়ার জন্য সময় পেয়েছি, যা এভাবে ল্যাম্বডায় রূপান্তরিত হতে পারে। সমস্ত ফাংশন কেবল একবার কল করা হয়েছিল এবং সুতরাং এটি একটি পদ্ধতিতে রাখা যেতে পারে। আমি তালিকাগুলি থেকে সেটগুলিতে স্যুইচ করেছি কারণ এটি কিছু অতিরিক্ত অক্ষর সংরক্ষণ করে। ঘোষণা একসাথে রাখা হয়েছে। তুলনা একসাথে করা হয়েছে এবং অক্ষরগুলি সেখানে ascii মান দ্বারা প্রতিস্থাপিত হয়েছে। পরিসীমা তুলনা অনেক অঞ্চল হিসাবে প্রকাশ করা যেতে পারে। ডাবলের মতো দীর্ঘ অভিব্যক্তিগুলি রোধ করতে এখানে এবং সেখানে কিছু কৌশল NNEGATIVE_INFINITY সম্পন্ন হয়েছে। যেখানে সম্ভব ইনলাইন অ্যাসিগমেন্টগুলি সম্পন্ন হয়। আরও কিছুটা বাঁচাতে আমি ডিগ্রিগুলিতে কোণগুলি তুলনা করে রেডিয়ানের সাথে তুলনা করে স্যুইচ করেছি। পুরো পরিবর্তনটি 500 টিরও বেশি অক্ষর সাশ্রয় করেছে, আমি আশা করি এটি 1000 এর অধীনেই পেয়ে যাব;)
আমি যেখানে সম্ভব জেনেরিকগুলি সরিয়েছি এবং একটি উপাদান অ্যারে তৈরি করে রিটার্নের তুলনা কমিয়ে দিয়েছি এবং পরিবর্তে এর মানটি পরীক্ষা করেছি। আমি ডাবলকেও প্রতিস্থাপন করেছি N এখন এটি শেষ পর্যন্ত 1000 টিরও বেশি দীর্ঘ!
আমি কিছু অক্ষর সংরক্ষণ করতে ব্যক্তির অবস্থান এবং বিল্ডিং পুনরুদ্ধারের সন্ধানের জন্য লুপগুলি একত্রিত করেছি। দুর্ভাগ্যক্রমে এর জন্য আমাদের লুপটির বাইরে ফেরত সরানো এবং এখনও একটি বিরতি ব্যবহার করা প্রয়োজন তবে এবার কোনও লেবেল ছাড়াই। আমি মিশে গিয়ে তৈরি max
এবং distanceSquared
এবং min
এবং newDistanceSquared
তারা একই সময়ে প্রয়োজন হয় না। আমি পরিবর্তন Integer.MAX_VALUE
করতে 2e31-1
। এছাড়াও আমি একটি ধ্রুবক তৈরি করেছি half = 0.5
যা বিল্ডিংয়ের কোণগুলি গণনা করতে ব্যবহৃত হয়। এটি গল্ফযুক্ত সংস্করণে খাটো। সামগ্রিকভাবে আমরা আরও 30 টি অক্ষর সংরক্ষণ করেছি!